[aseprite] 187/308: Generalize View::setViewScroll() to blit valid/scrollable region automatically
Tobias Hansen
thansen at moszumanska.debian.org
Tue Mar 8 02:45:09 UTC 2016
This is an automated email from the git hooks/post-receive script.
thansen pushed a commit to branch master
in repository aseprite.
commit b0650f6afea1b860a8593fd4614ca272f8edbfac
Author: David Capello <davidcapello at gmail.com>
Date: Tue Jan 5 16:37:52 2016 -0300
Generalize View::setViewScroll() to blit valid/scrollable region automatically
With this change we are removing specific code to scroll the Editor widget.
Now if we use Editor::setEditorScroll() to scroll it should work as
View::setViewScroll(). In this way we remove the ugly "blitValidRegion"
parameter from setEditorScroll().
Changes:
* Removed Widget::scrollRegion() because each widget must control
valid/invalid regions after a ui::move_region() in a very specific way
(see View::setViewScroll() or Window::moveWindow)
* Invalidate the whole widget on Widget::setBoundsQuietly()
* Fixed problems blitting invalid regions/not yet updated/painted: using
the new ui::Manager::m_invalidRegion.
* Added View::onSetViewScroll() and View::onScrollRegion()
* Added FileListView to avoid moving the thumbnail region when we scroll
---
data/widgets/file_selector.xml | 4 +-
src/app/CMakeLists.txt | 3 +-
src/app/commands/cmd_scroll.cpp | 2 +-
src/app/ui/editor/drawing_state.cpp | 2 +-
src/app/ui/editor/editor.cpp | 51 +++-----
src/app/ui/editor/editor.h | 5 +-
src/app/ui/editor/editor_view.cpp | 31 ++++-
src/app/ui/editor/editor_view.h | 4 +-
src/app/ui/editor/moving_pixels_state.cpp | 2 +-
src/app/ui/editor/scrolling_state.cpp | 4 +-
src/app/ui/editor/state_with_wheel_behavior.cpp | 2 +-
src/app/ui/file_list.cpp | 64 ++++++---
src/app/ui/file_list.h | 10 +-
src/app/ui/file_list_view.cpp | 35 +++++
src/app/ui/file_list_view.h | 26 ++++
src/app/ui/file_selector.cpp | 9 +-
src/app/ui/file_selector.h | 4 +-
src/ui/manager.cpp | 7 +
src/ui/manager.h | 16 ++-
src/ui/scroll_region_event.h | 30 +++++
src/ui/view.cpp | 166 +++++++++++++++++++++---
src/ui/view.h | 5 +-
src/ui/widget.cpp | 39 +-----
src/ui/widget.h | 2 -
24 files changed, 395 insertions(+), 128 deletions(-)
diff --git a/data/widgets/file_selector.xml b/data/widgets/file_selector.xml
index ccaa288..8fc3b7c 100644
--- a/data/widgets/file_selector.xml
+++ b/data/widgets/file_selector.xml
@@ -1,5 +1,5 @@
<!-- ASEPRITE -->
-<!-- Copyright (C) 2001-2013, 2015 by David Capello -->
+<!-- Copyright (C) 2001-2016 by David Capello -->
<gui>
<window id="file_selector" text="">
<vbox id="main">
@@ -12,7 +12,7 @@
<button text="" id="new_folder_button" tooltip="New folder" />
<combobox id="location" expansive="true" />
</box>
- <view id="file_view" expansive="true" />
+ <vbox id="file_view_placeholder" expansive="true" />
<grid columns="2">
<label text="File name:" />
<box id="file_name_placeholder" cell_align="horizontal" />
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 275655b..cbbed1f 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -1,5 +1,5 @@
# Aseprite
-# Copyright (C) 2001-2015 David Capello
+# Copyright (C) 2001-2016 David Capello
# Generate a ui::Widget for each widget in a XML file
file(GLOB widget_files ${CMAKE_SOURCE_DIR}/data/widgets/*.xml)
@@ -366,6 +366,7 @@ add_library(app-lib
ui/editor/transform_handles.cpp
ui/editor/zooming_state.cpp
ui/file_list.cpp
+ ui/file_list_view.cpp
ui/file_selector.cpp
ui/font_popup.cpp
ui/frame_tag_window.cpp
diff --git a/src/app/commands/cmd_scroll.cpp b/src/app/commands/cmd_scroll.cpp
index cff9e56..e987971 100644
--- a/src/app/commands/cmd_scroll.cpp
+++ b/src/app/commands/cmd_scroll.cpp
@@ -129,7 +129,7 @@ void ScrollCommand::onExecute(Context* context)
case Down: delta.y = +m_quantity * pixels; break;
}
- current_editor->setEditorScroll(scroll+delta, true);
+ current_editor->setEditorScroll(scroll+delta);
}
std::string ScrollCommand::onGetFriendlyName() const
diff --git a/src/app/ui/editor/drawing_state.cpp b/src/app/ui/editor/drawing_state.cpp
index a20d922..f2bb12b 100644
--- a/src/app/ui/editor/drawing_state.cpp
+++ b/src/app/ui/editor/drawing_state.cpp
@@ -169,7 +169,7 @@ bool DrawingState::onMouseMove(Editor* editor, MouseMessage* msg)
HideBrushPreview hide(editor->brushPreview());
// Infinite scroll
- gfx::Point mousePos = editor->autoScroll(msg, AutoScroll::MouseDir, true);
+ gfx::Point mousePos = editor->autoScroll(msg, AutoScroll::MouseDir);
tools::ToolLoopManager::Pointer pointer(editor->screenToEditor(mousePos),
button_from_msg(msg));
diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp
index a0ba039..456419b 100644
--- a/src/app/ui/editor/editor.cpp
+++ b/src/app/ui/editor/editor.cpp
@@ -288,6 +288,15 @@ void Editor::backToPreviousState()
setStateInternal(EditorStatePtr(NULL));
}
+void Editor::getInvalidDecoratoredRegion(gfx::Region& region)
+{
+ // Remove decorated region that cannot be just moved because it
+ // must be redrawn in another position when the Editor's scroll
+ // changes (e.g. symmetry handles).
+ if ((m_flags & kShowDecorators) && m_decorator)
+ m_decorator->getInvalidDecoratoredRegion(this, region);
+}
+
void Editor::setLayer(const Layer* layer)
{
bool changed = (m_layer != layer);
@@ -354,39 +363,13 @@ void Editor::setDefaultScroll()
setEditorScroll(
gfx::Point(
m_padding.x - vp.w/2 + m_zoom.apply(m_sprite->width())/2,
- m_padding.y - vp.h/2 + m_zoom.apply(m_sprite->height())/2), false);
+ m_padding.y - vp.h/2 + m_zoom.apply(m_sprite->height())/2));
}
// Sets the scroll position of the editor
-void Editor::setEditorScroll(const gfx::Point& scroll, bool blitValidRegion)
+void Editor::setEditorScroll(const gfx::Point& scroll)
{
- HideBrushPreview hide(m_brushPreview);
- View* view = View::getView(this);
- Point oldScroll;
- Region region;
- Region invalidRegion;
-
- if (blitValidRegion) {
- getDrawableRegion(region, kCutTopWindows);
- oldScroll = view->viewScroll();
-
- // Remove decorated region that cannot be just moved because it
- // must be redrawn in another position when the Editor's scroll
- // changes (e.g. symmetry handles).
- if ((m_flags & kShowDecorators) && m_decorator) {
- m_decorator->getInvalidDecoratoredRegion(this, invalidRegion);
- if (!invalidRegion.isEmpty())
- region.createSubtraction(region, invalidRegion);
- }
- }
-
- view->setViewScroll(scroll);
- Point newScroll = view->viewScroll();
-
- if (blitValidRegion) {
- // Move screen with blits
- scrollRegion(region, oldScroll - newScroll);
- }
+ View::getView(this)->setViewScroll(scroll);
}
void Editor::setEditorZoom(const render::Zoom& zoom)
@@ -862,7 +845,7 @@ void Editor::flashCurrentLayer()
}
}
-gfx::Point Editor::autoScroll(MouseMessage* msg, AutoScroll dir, bool blitValidRegion)
+gfx::Point Editor::autoScroll(MouseMessage* msg, AutoScroll dir)
{
// // Hide the brush preview
// HideBrushPreview hide(editor->brushPreview());
@@ -891,7 +874,7 @@ gfx::Point Editor::autoScroll(MouseMessage* msg, AutoScroll dir, bool blitValidR
else {
scroll -= deltaScroll;
}
- setEditorScroll(scroll, blitValidRegion);
+ setEditorScroll(scroll);
#if defined(_WIN32) || defined(__APPLE__)
mousePos -= delta;
@@ -1101,7 +1084,7 @@ void Editor::centerInSpritePoint(const gfx::Point& spritePos)
m_padding.y - (vp.h/2) + m_zoom.apply(1)/2 + m_zoom.apply(spritePos.y));
updateEditor();
- setEditorScroll(scroll, false);
+ setEditorScroll(scroll);
invalidate();
}
@@ -1498,12 +1481,10 @@ void Editor::setZoomAndCenterInMouse(const Zoom& zoom,
padding.y - (screenPos.y-vp.y) + zoom.apply(spritePos.y+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.y)));
if ((m_zoom != zoom) || (screenPos != view->viewScroll())) {
- bool blitValidRegion = (m_zoom == zoom);
-
m_zoom = zoom;
updateEditor();
- setEditorScroll(scrollPos, blitValidRegion);
+ setEditorScroll(scrollPos);
}
flushRedraw();
diff --git a/src/app/ui/editor/editor.h b/src/app/ui/editor/editor.h
index df138c9..479483c 100644
--- a/src/app/ui/editor/editor.h
+++ b/src/app/ui/editor/editor.h
@@ -109,6 +109,7 @@ namespace app {
// the Editor, so it must be deleted by the caller.
EditorDecorator* decorator() { return m_decorator; }
void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; }
+ void getInvalidDecoratoredRegion(gfx::Region& region);
EditorFlags editorFlags() const { return m_flags; }
void setEditorFlags(EditorFlags flags) { m_flags = flags; }
@@ -129,7 +130,7 @@ namespace app {
void setZoom(const render::Zoom& zoom) { m_zoom = zoom; }
void setDefaultScroll();
- void setEditorScroll(const gfx::Point& scroll, bool blitValidRegion);
+ void setEditorScroll(const gfx::Point& scroll);
void setEditorZoom(const render::Zoom& zoom);
// Updates the Editor's view.
@@ -164,7 +165,7 @@ namespace app {
void updateStatusBar();
// Control scroll when cursor goes out of the editor viewport.
- gfx::Point autoScroll(ui::MouseMessage* msg, AutoScroll dir, bool blitValidRegion);
+ gfx::Point autoScroll(ui::MouseMessage* msg, AutoScroll dir);
tools::Tool* getCurrentEditorTool();
tools::Ink* getCurrentEditorInk();
diff --git a/src/app/ui/editor/editor_view.cpp b/src/app/ui/editor/editor_view.cpp
index d59b859..6516e7b 100644
--- a/src/app/ui/editor/editor_view.cpp
+++ b/src/app/ui/editor/editor_view.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,7 @@
#include "she/surface.h"
#include "ui/paint_event.h"
#include "ui/resize_event.h"
+#include "ui/scroll_region_event.h"
namespace app {
@@ -106,7 +107,7 @@ void EditorView::onResize(ResizeEvent& ev)
// This keeps the same scroll position for the editor
gfx::Point newPos = editor->editorToScreen(gfx::Point(0, 0));
gfx::Point oldScroll = viewScroll();
- editor->setEditorScroll(oldScroll + newPos - oldPos, false);
+ editor->setEditorScroll(oldScroll + newPos - oldPos);
break;
}
case KeepCenter:
@@ -116,6 +117,32 @@ void EditorView::onResize(ResizeEvent& ev)
}
}
+void EditorView::onSetViewScroll(const gfx::Point& pt)
+{
+ Editor* editor = this->editor();
+ if (editor) {
+ // We have to hide the brush preview to scroll (without this,
+ // keyboard shortcuts to scroll when the brush preview is visible
+ // will leave brush previews all over the screen).
+ HideBrushPreview hide(editor->brushPreview());
+ View::onSetViewScroll(pt);
+ }
+}
+
+void EditorView::onScrollRegion(ui::ScrollRegionEvent& ev)
+{
+ View::onScrollRegion(ev);
+
+ gfx::Region& region = ev.region();
+ Editor* editor = this->editor();
+ ASSERT(editor);
+ if (editor) {
+ gfx::Region invalidRegion;
+ editor->getInvalidDecoratoredRegion(invalidRegion);
+ region.createSubtraction(region, invalidRegion);
+ }
+}
+
void EditorView::onScrollChange()
{
View::onScrollChange();
diff --git a/src/app/ui/editor/editor_view.h b/src/app/ui/editor/editor_view.h
index 236cae6..e7a9321 100644
--- a/src/app/ui/editor/editor_view.h
+++ b/src/app/ui/editor/editor_view.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -27,6 +27,8 @@ namespace app {
protected:
void onPaint(ui::PaintEvent& ev) override;
void onResize(ui::ResizeEvent& ev) override;
+ void onSetViewScroll(const gfx::Point& pt) override;
+ void onScrollRegion(ui::ScrollRegionEvent& ev) override;
void onScrollChange() override;
private:
diff --git a/src/app/ui/editor/moving_pixels_state.cpp b/src/app/ui/editor/moving_pixels_state.cpp
index 209791d..9f3e03f 100644
--- a/src/app/ui/editor/moving_pixels_state.cpp
+++ b/src/app/ui/editor/moving_pixels_state.cpp
@@ -309,7 +309,7 @@ bool MovingPixelsState::onMouseMove(Editor* editor, MouseMessage* msg)
// If there is a button pressed
if (m_pixelsMovement->isDragging()) {
// Auto-scroll
- gfx::Point mousePos = editor->autoScroll(msg, AutoScroll::MouseDir, false);
+ gfx::Point mousePos = editor->autoScroll(msg, AutoScroll::MouseDir);
// Get the position of the mouse in the sprite
gfx::Point spritePos = editor->screenToEditor(mousePos);
diff --git a/src/app/ui/editor/scrolling_state.cpp b/src/app/ui/editor/scrolling_state.cpp
index 84c2720..3bd9ba6 100644
--- a/src/app/ui/editor/scrolling_state.cpp
+++ b/src/app/ui/editor/scrolling_state.cpp
@@ -54,7 +54,7 @@ bool ScrollingState::onMouseMove(Editor* editor, MouseMessage* msg)
gfx::Point newPos = msg->position();
#ifdef _WIN32
- if (newPos != editor->autoScroll(msg, AutoScroll::ScrollDir, true)) {
+ if (newPos != editor->autoScroll(msg, AutoScroll::ScrollDir)) {
m_oldPos = newPos;
return true;
}
@@ -63,7 +63,7 @@ bool ScrollingState::onMouseMove(Editor* editor, MouseMessage* msg)
scroll -= newPos - m_oldPos;
m_oldPos = newPos;
- editor->setEditorScroll(scroll, true);
+ editor->setEditorScroll(scroll);
return true;
}
diff --git a/src/app/ui/editor/state_with_wheel_behavior.cpp b/src/app/ui/editor/state_with_wheel_behavior.cpp
index 4627c8a..50b83fc 100644
--- a/src/app/ui/editor/state_with_wheel_behavior.cpp
+++ b/src/app/ui/editor/state_with_wheel_behavior.cpp
@@ -153,7 +153,7 @@ bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
}
}
- editor->setEditorScroll(scroll+delta, true);
+ editor->setEditorScroll(scroll+delta);
break;
}
diff --git a/src/app/ui/file_list.cpp b/src/app/ui/file_list.cpp
index 75a026f..006ebbc 100644
--- a/src/app/ui/file_list.cpp
+++ b/src/app/ui/file_list.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -35,6 +35,7 @@ FileList::FileList()
: Widget(kGenericWidget)
, m_generateThumbnailTimer(200, this)
, m_monitoringTimer(50, this)
+ , m_thumbnail(nullptr)
{
setFocusStop(true);
setDoubleBuffered(true);
@@ -302,6 +303,22 @@ bool FileList::onProcessMessage(Message* msg)
return Widget::onProcessMessage(msg);
}
+int FileList::thumbnailY()
+{
+ int y = 0;
+ for (IFileItem* fi : m_list) {
+ gfx::Size itemSize = getFileItemSize(fi);
+ if (fi == m_selected) {
+ if (fi->getThumbnail())
+ return y + itemSize.h/2;
+ else
+ break;
+ }
+ y += itemSize.h;
+ }
+ return 0;
+}
+
void FileList::onPaint(ui::PaintEvent& ev)
{
Graphics* g = ev.graphics();
@@ -313,15 +330,12 @@ void FileList::onPaint(ui::PaintEvent& ev)
int evenRow = 0;
gfx::Color bgcolor;
gfx::Color fgcolor;
- she::Surface* thumbnail = NULL;
- int thumbnail_y = 0;
g->fillRect(theme->colors.background(), bounds);
// rows
- for (FileItemList::iterator
- it=m_list.begin(), end=m_list.end(); it!=end; ++it) {
- IFileItem* fi = *it;
+ m_thumbnail = nullptr;
+ for (IFileItem* fi : m_list) {
gfx::Size itemSize = getFileItemSize(fi);
if (fi == m_selected) {
@@ -373,30 +387,38 @@ void FileList::onPaint(ui::PaintEvent& ev)
}
// Thumbnail position
- if (fi == m_selected) {
- thumbnail = fi->getThumbnail();
- if (thumbnail)
- thumbnail_y = y + itemSize.h/2;
- }
+ if (fi == m_selected)
+ m_thumbnail = fi->getThumbnail();
y += itemSize.h;
evenRow ^= 1;
}
// Draw the thumbnail
- if (thumbnail) {
- x = vp.x+vp.w - 2*guiscale() - thumbnail->width();
- y = thumbnail_y - thumbnail->height()/2 + this->bounds().y;
- y = MID(vp.y+2*guiscale(), y, vp.y+vp.h-3*guiscale()-thumbnail->height());
- x -= this->bounds().x;
- y -= this->bounds().y;
-
- g->blit(thumbnail, 0, 0, x, y, thumbnail->width(), thumbnail->height());
- g->drawRect(gfx::rgba(0, 0, 0),
- gfx::Rect(x-1, y-1, thumbnail->width()+1, thumbnail->height()+1));
+ if (m_thumbnail) {
+ gfx::Rect tbounds = thumbnailBounds();
+ g->blit(m_thumbnail, 0, 0, tbounds.x, tbounds.y, tbounds.w, tbounds.h);
+ g->drawRect(gfx::rgba(0, 0, 0), tbounds.enlarge(1));
}
}
+gfx::Rect FileList::thumbnailBounds()
+{
+ if (!m_selected ||
+ !m_selected->getThumbnail())
+ return gfx::Rect();
+
+ she::Surface* thumbnail = m_selected->getThumbnail();
+ View* view = View::getView(this);
+ gfx::Rect vp = view->viewportBounds();
+ int x = vp.x+vp.w - 2*guiscale() - thumbnail->width();
+ int y = thumbnailY() - thumbnail->height()/2 + bounds().y;
+ y = MID(vp.y+2*guiscale(), y, vp.y+vp.h-3*guiscale()-thumbnail->height());
+ x -= bounds().x;
+ y -= bounds().y;
+ return gfx::Rect(x, y, thumbnail->width(), thumbnail->height());
+}
+
void FileList::onSizeHint(SizeHintEvent& ev)
{
if (!m_req_valid) {
diff --git a/src/app/ui/file_list.h b/src/app/ui/file_list.h
index bbefc2c..8e4a8cc 100644
--- a/src/app/ui/file_list.h
+++ b/src/app/ui/file_list.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -16,6 +16,10 @@
#include <string>
+namespace she {
+ class Surface;
+}
+
namespace app {
class FileList : public ui::Widget {
@@ -34,6 +38,8 @@ namespace app {
void goUp();
+ gfx::Rect thumbnailBounds();
+
base::Signal0<void> FileSelected;
base::Signal0<void> FileAccepted;
base::Signal0<void> CurrentFolderChanged;
@@ -55,6 +61,7 @@ namespace app {
int getSelectedIndex();
void selectIndex(int index);
void generatePreviewOfSelectedItem();
+ int thumbnailY();
IFileItem* m_currentFolder;
FileItemList m_list;
@@ -78,6 +85,7 @@ namespace app {
// thumbnail to generate when the m_generateThumbnailTimer ticks.
IFileItem* m_itemToGenerateThumbnail;
+ she::Surface* m_thumbnail;
};
} // namespace app
diff --git a/src/app/ui/file_list_view.cpp b/src/app/ui/file_list_view.cpp
new file mode 100644
index 0000000..be0378d
--- /dev/null
+++ b/src/app/ui/file_list_view.cpp
@@ -0,0 +1,35 @@
+// Aseprite
+// Copyright (C) 2016 David Capello
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app/ui/file_list_view.h"
+
+#include "app/ui/file_list.h"
+#include "ui/scroll_region_event.h"
+
+namespace app {
+
+void FileListView::onScrollRegion(ui::ScrollRegionEvent& ev)
+{
+ View::onScrollRegion(ev);
+
+ if (auto fileList = dynamic_cast<FileList*>(attachedWidget())) {
+ gfx::Rect tbounds = fileList->thumbnailBounds();
+ if (!tbounds.isEmpty()) {
+ tbounds
+ .enlarge(1)
+ .offset(fileList->bounds().origin());
+
+ ev.region().createSubtraction(ev.region(), gfx::Region(tbounds));
+ }
+ }
+}
+
+} // namespace app
diff --git a/src/app/ui/file_list_view.h b/src/app/ui/file_list_view.h
new file mode 100644
index 0000000..e1c722a
--- /dev/null
+++ b/src/app/ui/file_list_view.h
@@ -0,0 +1,26 @@
+// Aseprite
+// Copyright (C) 2016 David Capello
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+
+#ifndef APP_UI_FILE_LIST_VIEW_H_INCLUDED
+#define APP_UI_FILE_LIST_VIEW_H_INCLUDED
+#pragma once
+
+#include "ui/view.h"
+
+namespace app {
+
+ class FileListView : public ui::View {
+ public:
+ FileListView() { }
+
+ private:
+ void onScrollRegion(ui::ScrollRegionEvent& ev);
+ };
+
+} // namespace app
+
+#endif
diff --git a/src/app/ui/file_selector.cpp b/src/app/ui/file_selector.cpp
index b9838d9..63e6bdc 100644
--- a/src/app/ui/file_selector.cpp
+++ b/src/app/ui/file_selector.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -19,6 +19,7 @@
#include "app/modules/gui.h"
#include "app/recent_files.h"
#include "app/ui/file_list.h"
+#include "app/ui/file_list_view.h"
#include "app/ui/skin/button_icon_impl.h"
#include "app/ui/skin/skin_theme.h"
#include "app/widget_loader.h"
@@ -280,9 +281,13 @@ FileSelector::FileSelector(FileSelectorType type, FileSelectorDelegate* delegate
m_fileList = new FileList();
m_fileList->setId("fileview");
- fileView()->attachToView(m_fileList);
m_fileName->setAssociatedFileList(m_fileList);
+ m_fileView = new FileListView();
+ m_fileView->attachToView(m_fileList);
+ m_fileView->setExpansive(true);
+ fileViewPlaceholder()->addChild(m_fileView);
+
goBackButton()->Click.connect(base::Bind<void>(&FileSelector::onGoBack, this));
goForwardButton()->Click.connect(base::Bind<void>(&FileSelector::onGoForward, this));
goUpButton()->Click.connect(base::Bind<void>(&FileSelector::onGoUp, this));
diff --git a/src/app/ui/file_selector.h b/src/app/ui/file_selector.h
index fde96c5..6a1a67a 100644
--- a/src/app/ui/file_selector.h
+++ b/src/app/ui/file_selector.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@@ -26,6 +26,7 @@ namespace ui {
namespace app {
class CustomFileNameEntry;
class FileList;
+ class FileListView;
class IFileItem;
class FileSelector : public app::gen::FileSelector {
@@ -62,6 +63,7 @@ namespace app {
std::string m_defExtension;
CustomFileNameEntry* m_fileName;
FileList* m_fileList;
+ FileListView* m_fileView;
// If true the navigation_history isn't
// modified if the current folder changes
diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp
index 0f2015c..1ab31dd 100644
--- a/src/ui/manager.cpp
+++ b/src/ui/manager.cpp
@@ -1058,6 +1058,9 @@ void Manager::onResize(ResizeEvent& ev)
gfx::Rect new_pos = ev.bounds();
setBoundsQuietly(new_pos);
+ // The whole manager area is invalid now.
+ m_invalidRegion = gfx::Region(new_pos);
+
int dx = new_pos.x - old_pos.x;
int dy = new_pos.y - old_pos.y;
int dw = new_pos.w - old_pos.w;
@@ -1266,6 +1269,10 @@ void Manager::pumpQueue()
// Restore clip region for paint messages.
surface->setClipBounds(oldClip);
}
+
+ // As this kPaintMessage's rectangle was updated, we can
+ // remove it from "m_invalidRegion".
+ m_invalidRegion -= gfx::Region(paintMsg->rect());
}
}
else {
diff --git a/src/ui/manager.h b/src/ui/manager.h
index bc91410..0b603cc 100644
--- a/src/ui/manager.h
+++ b/src/ui/manager.h
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -86,6 +86,19 @@ namespace ui {
bool isFocusMovementKey(Message* msg);
+ // Returns the invalid region in the screen to being updated with
+ // PaintMessages. This region is cleared when each widget receives
+ // a paint message.
+ const gfx::Region& getInvalidRegion() const {
+ return m_invalidRegion;
+ }
+
+ void addInvalidRegion(const gfx::Region& b) {
+ m_invalidRegion |= b;
+ }
+
+ // Mark the given rectangle as a area to be flipped to the real
+ // screen
void dirtyRect(const gfx::Rect& bounds);
void _openWindow(Window* window);
@@ -130,6 +143,7 @@ namespace ui {
she::Display* m_display;
she::Clipboard* m_clipboard;
she::EventQueue* m_eventQueue;
+ gfx::Region m_invalidRegion; // Invalid region (we didn't receive paint messages yet for this).
// This member is used to make freeWidget() a no-op when we
// restack a window if the user clicks on it.
diff --git a/src/ui/scroll_region_event.h b/src/ui/scroll_region_event.h
new file mode 100644
index 0000000..5b5a95b
--- /dev/null
+++ b/src/ui/scroll_region_event.h
@@ -0,0 +1,30 @@
+// Aseprite UI Library
+// Copyright (C) 2015 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef UI_SCROLL_REGION_EVENT_H_INCLUDED
+#define UI_SCROLL_REGION_EVENT_H_INCLUDED
+#pragma once
+
+#include "gfx/region.h"
+#include "ui/event.h"
+
+namespace ui {
+
+ class ScrollRegionEvent : public Event {
+ public:
+ ScrollRegionEvent(Component* source, gfx::Region& region)
+ : Event(source), m_region(region) {
+ }
+
+ gfx::Region& region() { return m_region; }
+
+ private:
+ gfx::Region& m_region;
+ };
+
+} // namespace ui
+
+#endif
diff --git a/src/ui/view.cpp b/src/ui/view.cpp
index 754e6b6..b625dca 100644
--- a/src/ui/view.cpp
+++ b/src/ui/view.cpp
@@ -1,24 +1,37 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
+// #define DEBUG_SCROLL_EVENTS
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gfx/size.h"
#include "ui/intern.h"
+#include "ui/manager.h"
#include "ui/message.h"
-#include "ui/size_hint_event.h"
+#include "ui/move_region.h"
#include "ui/resize_event.h"
#include "ui/scroll_helper.h"
+#include "ui/scroll_region_event.h"
+#include "ui/size_hint_event.h"
#include "ui/system.h"
#include "ui/theme.h"
#include "ui/view.h"
#include "ui/widget.h"
+#ifdef DEBUG_SCROLL_EVENTS
+#include "base/thread.h"
+#include "she/display.h"
+#include "she/scoped_surface_lock.h"
+#endif
+
+#include <queue>
+
#define HBAR_SIZE (m_scrollbar_h.getBarWidth())
#define VBAR_SIZE (m_scrollbar_v.getBarWidth())
@@ -33,7 +46,7 @@ View::View()
{
m_hasBars = true;
- this->setFocusStop(true);
+ setFocusStop(true);
addChild(&m_viewport);
setScrollableSize(Size(0, 0));
@@ -128,21 +141,7 @@ Point View::viewScroll() const
void View::setViewScroll(const Point& pt)
{
- Point oldScroll = viewScroll();
- Size maxsize = getScrollableSize();
- Size visible = visibleSize();
- Point newScroll(MID(0, pt.x, MAX(0, maxsize.w - visible.w)),
- MID(0, pt.y, MAX(0, maxsize.h - visible.h)));
-
- if (newScroll == oldScroll)
- return;
-
- m_scrollbar_h.setPos(newScroll.x);
- m_scrollbar_v.setPos(newScroll.y);
-
- m_viewport.layout();
-
- onScrollChange();
+ onSetViewScroll(pt);
}
void View::updateView()
@@ -228,6 +227,137 @@ void View::onPaint(PaintEvent& ev)
theme()->paintView(ev);
}
+void View::onSetViewScroll(const gfx::Point& pt)
+{
+ Point oldScroll = viewScroll();
+ Size maxsize = getScrollableSize();
+ Size visible = visibleSize();
+ Point newScroll(MID(0, pt.x, MAX(0, maxsize.w - visible.w)),
+ MID(0, pt.y, MAX(0, maxsize.h - visible.h)));
+
+ if (newScroll == oldScroll)
+ return;
+
+ // This is the movement for the scrolled region (which is inverse to
+ // the scroll position delta/movement).
+ Point delta = oldScroll - newScroll;
+
+ // Visible viewport region that is not overlapped by windows
+ Region drawableRegion;
+ m_viewport.getDrawableRegion(
+ drawableRegion, DrawableRegionFlags(kCutTopWindows | kUseChildArea));
+
+ // Start the region to scroll equal to the drawable viewport region.
+ Rect cpos = m_viewport.childrenBounds();
+ Region validRegion(cpos);
+ validRegion &= drawableRegion;
+
+ // Remove all children invalid regions from this "validRegion"
+ {
+ std::queue<Widget*> items;
+ items.push(&m_viewport);
+ while (!items.empty()) {
+ Widget* item = items.front();
+ items.pop();
+ for (Widget* child : item->children())
+ items.push(child);
+
+ if (item->isVisible())
+ validRegion -= item->getUpdateRegion();
+ }
+ }
+
+ // Remove invalid region in the screen (areas that weren't
+ // re-painted yet)
+ Manager* manager = this->manager();
+ if (manager)
+ validRegion -= manager->getInvalidRegion();
+
+ // Add extra regions that cannot be scrolled (this can be customized
+ // by subclassing ui::View). We use two ScrollRegionEvent, this
+ // first one with the old scroll position. And the next one with the
+ // new scroll position.
+ {
+ ScrollRegionEvent ev(this, validRegion);
+ onScrollRegion(ev);
+ }
+
+ // Move viewport children
+ cpos.offset(-newScroll);
+ for (auto child : m_viewport.children()) {
+ Size reqSize = child->sizeHint();
+ cpos.w = MAX(reqSize.w, cpos.w);
+ cpos.h = MAX(reqSize.h, cpos.h);
+ if (cpos.w != child->bounds().w ||
+ cpos.h != child->bounds().h)
+ child->setBounds(cpos);
+ else
+ child->offsetWidgets(cpos.x - child->bounds().x,
+ cpos.y - child->bounds().y);
+ }
+
+ // Change scroll bar positions
+ m_scrollbar_h.setPos(newScroll.x);
+ m_scrollbar_v.setPos(newScroll.y);
+
+ // Region to invalidate (new visible children/child parts)
+ Region invalidRegion(cpos);
+ invalidRegion &= drawableRegion;
+
+ // Move the valid screen region.
+ {
+ // The movable region includes the given "validRegion"
+ // intersecting itself when it's in the new position, so we don't
+ // overlap regions outside the "validRegion".
+ Region movable = validRegion;
+ movable.offset(delta);
+ movable &= validRegion;
+ invalidRegion -= movable; // Remove the moved region as invalid
+ movable.offset(-delta);
+
+ ui::move_region(manager, movable, delta.x, delta.y);
+ }
+
+#ifdef DEBUG_SCROLL_EVENTS
+ // Paint invalid region with red fill
+ {
+ auto display = manager->getDisplay();
+ if (display)
+ display->flip(gfx::Rect(0, 0, display_w(), display_h()));
+ base::this_thread::sleep_for(0.002);
+ {
+ she::ScopedSurfaceLock lock(display->getSurface());
+ for (const auto& rc : invalidRegion)
+ lock->fillRect(gfx::rgba(255, 0, 0), rc);
+ }
+ if (display)
+ display->flip(gfx::Rect(0, 0, display_w(), display_h()));
+ base::this_thread::sleep_for(0.002);
+ }
+#endif
+
+ // Don't re-invalidate the already invalid region.
+ if (manager)
+ invalidRegion -= manager->getInvalidRegion();
+
+ // Invalidate viewport's children regions
+ m_viewport.invalidateRegion(invalidRegion);
+
+ // Notify about the new scroll position
+ onScrollChange();
+
+ // Generate PaintMessages right now when the invalid region is too
+ // disaggregated. This is useful to avoid a lot of PaintMessage with
+ // small rectangles.
+ if (manager->getInvalidRegion().size() > 4)
+ flushRedraw();
+}
+
+void View::onScrollRegion(ScrollRegionEvent& ev)
+{
+ // Do nothing
+}
+
void View::onScrollChange()
{
// Do nothing
diff --git a/src/ui/view.h b/src/ui/view.h
index f97d40a..f07efe4 100644
--- a/src/ui/view.h
+++ b/src/ui/view.h
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2013, 2015, 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -15,6 +15,7 @@
#include "ui/widget.h"
namespace ui {
+ class ScrollRegionEvent;
class View : public Widget
, public ScrollableViewDelegate {
@@ -57,6 +58,8 @@ namespace ui {
void onSizeHint(SizeHintEvent& ev) override;
void onPaint(PaintEvent& ev) override;
+ virtual void onSetViewScroll(const gfx::Point& pt);
+ virtual void onScrollRegion(ScrollRegionEvent& ev);
virtual void onScrollChange();
private:
diff --git a/src/ui/widget.cpp b/src/ui/widget.cpp
index 3ebcea2..231ff13 100644
--- a/src/ui/widget.cpp
+++ b/src/ui/widget.cpp
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -617,8 +617,8 @@ void Widget::setBounds(const Rect& rc)
void Widget::setBoundsQuietly(const gfx::Rect& rc)
{
- m_updateRegion.offset(rc.x - m_bounds.x, rc.y - m_bounds.y);
m_bounds = rc;
+ invalidate();
}
void Widget::setBorder(const Border& br)
@@ -874,6 +874,9 @@ void Widget::flushRedraw()
processing.push(this);
}
+ Manager* manager = this->manager();
+ ASSERT(manager);
+
while (!processing.empty()) {
Widget* widget = processing.front();
processing.pop();
@@ -910,9 +913,10 @@ void Widget::flushRedraw()
msg->addRecipient(widget);
// Enqueue the draw message
- manager()->enqueueMessage(msg);
+ manager->enqueueMessage(msg);
}
+ manager->addInvalidRegion(widget->m_updateRegion);
widget->m_updateRegion.clear();
}
}
@@ -1036,35 +1040,6 @@ void Widget::invalidateRegion(const Region& region)
onInvalidateRegion(region);
}
-void Widget::scrollRegion(const Region& region, const Point& delta)
-{
- if (delta.x == 0 && delta.y == 0)
- return;
-
- // The movable region includes the given region in the "region"
- // parameter without the invalid widget region (i.e. m_updateRegion,
- // as we cannot move invalid/non-updated screen areas), and
- // intersecting with the moved "region" area (so we don't overlap
- // regions outside the "region" parameters)
- Region movable = region;
- movable.createSubtraction(movable, m_updateRegion);
- movable.offset(delta);
- movable.createIntersection(movable, region);
-
- // Now we invalidate the given "region" without the moved region
- // ("movable" variable).
- m_updateRegion.createUnion(m_updateRegion, region);
- m_updateRegion.createSubtraction(m_updateRegion, movable);
- mark_dirty_flag(this);
-
- // Move screen pixels
- movable.offset(-delta);
- ui::move_region(manager(), movable, delta.x, delta.y);
-
- // Generate the kPaintMessage messages for the widget's m_updateRegion
- flushRedraw();
-}
-
class DeleteGraphicsAndSurface {
public:
DeleteGraphicsAndSurface(const gfx::Rect& clip, she::Surface* surface)
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 092290b..54a9c2a 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -306,8 +306,6 @@ namespace ui {
// Generates paint messages for the current update region.
void flushRedraw();
- void scrollRegion(const gfx::Region& region, const gfx::Point& delta);
-
GraphicsPtr getGraphics(const gfx::Rect& clip);
// ===============================================================
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git
More information about the Pkg-games-commits
mailing list