mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Add feedback to Workspace to drop tabs on it
This commit is contained in:
		
							parent
							
								
									9e27930f95
								
							
						
					
					
						commit
						2cfef9e250
					
				|  | @ -247,6 +247,17 @@ void MainWindow::onActiveViewChange() | |||
|   configureWorkspaceLayout(); | ||||
| } | ||||
| 
 | ||||
| bool MainWindow::onIsModified(Tabs* tabs, TabView* tabView) | ||||
| { | ||||
|   if (DocumentView* docView = dynamic_cast<DocumentView*>(tabView)) { | ||||
|     Document* document = docView->getDocument(); | ||||
|     return document->isModified(); | ||||
|   } | ||||
|   else { | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void MainWindow::onSelectTab(Tabs* tabs, TabView* tabView) | ||||
| { | ||||
|   if (!tabView) | ||||
|  | @ -286,15 +297,16 @@ void MainWindow::onMouseOverTab(Tabs* tabs, TabView* tabView) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| bool MainWindow::onIsModified(Tabs* tabs, TabView* tabView) | ||||
| void MainWindow::onFloatingTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos) | ||||
| { | ||||
|   if (DocumentView* docView = dynamic_cast<DocumentView*>(tabView)) { | ||||
|     Document* document = docView->getDocument(); | ||||
|     return document->isModified(); | ||||
|   } | ||||
|   else { | ||||
|     return false; | ||||
|   } | ||||
|   m_workspace->setDropViewPreview(pos); | ||||
| } | ||||
| 
 | ||||
| DropTabResult MainWindow::onDropTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos) | ||||
| { | ||||
|   m_workspace->removeDropViewPreview(pos); | ||||
|   m_workspace->dropViewAt(pos, dynamic_cast<WorkspaceView*>(tabView)); | ||||
|   return DropTabResult::IGNORE; | ||||
| } | ||||
| 
 | ||||
| void MainWindow::configureWorkspaceLayout() | ||||
|  |  | |||
|  | @ -74,11 +74,13 @@ namespace app { | |||
|     void popTimeline(); | ||||
| 
 | ||||
|     // TabsDelegate implementation.
 | ||||
|     bool onIsModified(Tabs* tabs, TabView* tabView) override; | ||||
|     void onSelectTab(Tabs* tabs, TabView* tabView) override; | ||||
|     void onCloseTab(Tabs* tabs, TabView* tabView) override; | ||||
|     void onContextMenuTab(Tabs* tabs, TabView* tabView) override; | ||||
|     void onMouseOverTab(Tabs* tabs, TabView* tabView) override; | ||||
|     bool onIsModified(Tabs* tabs, TabView* tabView) override; | ||||
|     void onFloatingTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos) override; | ||||
|     DropTabResult onDropTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos) override; | ||||
| 
 | ||||
|   protected: | ||||
|     bool onProcessMessage(ui::Message* msg) override; | ||||
|  |  | |||
|  | @ -250,6 +250,9 @@ bool Tabs::onProcessMessage(Message* msg) | |||
|               createFloatingTab(m_selected); | ||||
| 
 | ||||
|             m_floatingOverlay->moveOverlay(mousePos - m_dragOffset); | ||||
| 
 | ||||
|             if (m_delegate) | ||||
|               m_delegate->onFloatingTab(this, m_selected->view, mousePos); | ||||
|           } | ||||
|           else { | ||||
|             justDocked = m_floatingTab; | ||||
|  | @ -332,8 +335,13 @@ bool Tabs::onProcessMessage(Message* msg) | |||
| 
 | ||||
|         releaseMouse(); | ||||
| 
 | ||||
|         if (m_isDragging) | ||||
|         if (m_isDragging) { | ||||
|           if (m_delegate) | ||||
|             m_delegate->onDropTab(this, m_selected->view, | ||||
|               mouseMsg->position()); | ||||
| 
 | ||||
|           stopDrag(); | ||||
|         } | ||||
| 
 | ||||
|         if (m_clickedCloseButton) { | ||||
|           m_clickedCloseButton = false; | ||||
|  |  | |||
|  | @ -41,11 +41,20 @@ namespace app { | |||
|     virtual TabIcon getTabIcon() = 0; | ||||
|   }; | ||||
| 
 | ||||
|   enum class DropTabResult { | ||||
|     IGNORE, | ||||
|     DOCKED_IN_OTHER_PLACE, | ||||
|   }; | ||||
| 
 | ||||
|   // Interface used to control notifications from the Tabs widget.
 | ||||
|   class TabsDelegate { | ||||
|   public: | ||||
| 
 | ||||
|     virtual ~TabsDelegate() { } | ||||
| 
 | ||||
|     // Returns true if the tab represent a modified document.
 | ||||
|     virtual bool onIsModified(Tabs* tabs, TabView* tabView) = 0; | ||||
| 
 | ||||
|     // Called when the user selected the tab with the left mouse button.
 | ||||
|     virtual void onSelectTab(Tabs* tabs, TabView* tabView) = 0; | ||||
| 
 | ||||
|  | @ -59,7 +68,9 @@ namespace app { | |||
|     // mouse just leave all tabs)
 | ||||
|     virtual void onMouseOverTab(Tabs* tabs, TabView* tabView) = 0; | ||||
| 
 | ||||
|     virtual bool onIsModified(Tabs* tabs, TabView* tabView) = 0; | ||||
|     // Called when the user is dragging a tab outside the Tabs bar.
 | ||||
|     virtual void onFloatingTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos) = 0; | ||||
|     virtual DropTabResult onDropTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos) = 0; | ||||
|   }; | ||||
| 
 | ||||
|   // Tabs control. Used to show opened documents.
 | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ Workspace::Workspace() | |||
|   : Widget(kGenericWidget) | ||||
|   , m_tabsBar(nullptr) | ||||
|   , m_activeView(nullptr) | ||||
|   , m_dropPreview(false) | ||||
| { | ||||
|   SkinTheme* theme = static_cast<SkinTheme*>(getTheme()); | ||||
|   setBgColor(theme->colors.workspace()); | ||||
|  | @ -100,4 +101,58 @@ void Workspace::onPaint(PaintEvent& ev) | |||
|   ev.getGraphics()->fillRect(getBgColor(), getClientBounds()); | ||||
| } | ||||
| 
 | ||||
| void Workspace::onResize(ui::ResizeEvent& ev) | ||||
| { | ||||
|   setBoundsQuietly(ev.getBounds()); | ||||
| 
 | ||||
|   gfx::Rect cpos = getChildrenBounds(); | ||||
| 
 | ||||
|   // Preview to drop tabs in workspace
 | ||||
|   if (m_dropPreview && cpos.contains(m_dropPos)) { | ||||
|     int left = ABS(cpos.x - m_dropPos.x); | ||||
|     int top = ABS(cpos.y - m_dropPos.y); | ||||
|     int right = ABS(cpos.x + cpos.w - m_dropPos.x); | ||||
|     int bottom = ABS(cpos.y + cpos.h - m_dropPos.y); | ||||
|     int threshold = 32*guiscale(); | ||||
|     if (threshold > cpos.w/2) threshold = cpos.w/2; | ||||
|     if (threshold > cpos.h/2) threshold = cpos.h/2; | ||||
| 
 | ||||
|     if (left < threshold && left < right && left < top && left < bottom) { | ||||
|       cpos.x += threshold; | ||||
|       cpos.w -= threshold; | ||||
|     } | ||||
|     else if (top < threshold && top < left && top < right && top < bottom) { | ||||
|       cpos.y += threshold; | ||||
|       cpos.h -= threshold; | ||||
|     } | ||||
|     else if (right < threshold && right < left && right < top && right < bottom) { | ||||
|       cpos.w -= threshold; | ||||
|     } | ||||
|     else if (bottom < threshold && bottom < left && bottom < top && bottom < right) { | ||||
|       cpos.h -= threshold; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   for (Widget* child : getChildren()) | ||||
|     child->setBounds(cpos); | ||||
| } | ||||
| 
 | ||||
| void Workspace::setDropViewPreview(const gfx::Point& pos) | ||||
| { | ||||
|   m_dropPos = pos; | ||||
|   m_dropPreview = true; | ||||
| 
 | ||||
|   layout(); | ||||
| } | ||||
| 
 | ||||
| void Workspace::removeDropViewPreview(const gfx::Point& pos) | ||||
| { | ||||
|   m_dropPreview = false; | ||||
|   layout(); | ||||
| } | ||||
| 
 | ||||
| void Workspace::dropViewAt(const gfx::Point& pos, WorkspaceView* view) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| } // namespace app
 | ||||
|  |  | |||
|  | @ -40,15 +40,23 @@ namespace app { | |||
|     WorkspaceView* activeView(); | ||||
|     void setActiveView(WorkspaceView* view); | ||||
| 
 | ||||
|     // Drop views into workspace
 | ||||
|     void setDropViewPreview(const gfx::Point& pos); | ||||
|     void removeDropViewPreview(const gfx::Point& pos); | ||||
|     void dropViewAt(const gfx::Point& pos, WorkspaceView* view); | ||||
| 
 | ||||
|     Signal0<void> ActiveViewChanged; | ||||
| 
 | ||||
|   protected: | ||||
|     void onPaint(ui::PaintEvent& ev) override; | ||||
|     void onResize(ui::ResizeEvent& ev) override; | ||||
| 
 | ||||
|   private: | ||||
|     Tabs* m_tabsBar; | ||||
|     WorkspaceViews m_views; | ||||
|     WorkspaceView* m_activeView; | ||||
|     bool m_dropPreview; | ||||
|     gfx::Point m_dropPos; | ||||
|   }; | ||||
| 
 | ||||
| } // namespace app
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue