Add feedback to Workspace to drop tabs on it

This commit is contained in:
David Capello 2015-03-27 18:14:00 -03:00
parent 9e27930f95
commit 2cfef9e250
6 changed files with 107 additions and 11 deletions

View File

@ -247,6 +247,17 @@ void MainWindow::onActiveViewChange()
configureWorkspaceLayout(); 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) void MainWindow::onSelectTab(Tabs* tabs, TabView* tabView)
{ {
if (!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)) { m_workspace->setDropViewPreview(pos);
Document* document = docView->getDocument(); }
return document->isModified();
} DropTabResult MainWindow::onDropTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos)
else { {
return false; m_workspace->removeDropViewPreview(pos);
} m_workspace->dropViewAt(pos, dynamic_cast<WorkspaceView*>(tabView));
return DropTabResult::IGNORE;
} }
void MainWindow::configureWorkspaceLayout() void MainWindow::configureWorkspaceLayout()

View File

@ -74,11 +74,13 @@ namespace app {
void popTimeline(); void popTimeline();
// TabsDelegate implementation. // TabsDelegate implementation.
bool onIsModified(Tabs* tabs, TabView* tabView) override;
void onSelectTab(Tabs* tabs, TabView* tabView) override; void onSelectTab(Tabs* tabs, TabView* tabView) override;
void onCloseTab(Tabs* tabs, TabView* tabView) override; void onCloseTab(Tabs* tabs, TabView* tabView) override;
void onContextMenuTab(Tabs* tabs, TabView* tabView) override; void onContextMenuTab(Tabs* tabs, TabView* tabView) override;
void onMouseOverTab(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: protected:
bool onProcessMessage(ui::Message* msg) override; bool onProcessMessage(ui::Message* msg) override;

View File

@ -250,6 +250,9 @@ bool Tabs::onProcessMessage(Message* msg)
createFloatingTab(m_selected); createFloatingTab(m_selected);
m_floatingOverlay->moveOverlay(mousePos - m_dragOffset); m_floatingOverlay->moveOverlay(mousePos - m_dragOffset);
if (m_delegate)
m_delegate->onFloatingTab(this, m_selected->view, mousePos);
} }
else { else {
justDocked = m_floatingTab; justDocked = m_floatingTab;
@ -332,8 +335,13 @@ bool Tabs::onProcessMessage(Message* msg)
releaseMouse(); releaseMouse();
if (m_isDragging) if (m_isDragging) {
if (m_delegate)
m_delegate->onDropTab(this, m_selected->view,
mouseMsg->position());
stopDrag(); stopDrag();
}
if (m_clickedCloseButton) { if (m_clickedCloseButton) {
m_clickedCloseButton = false; m_clickedCloseButton = false;

View File

@ -41,11 +41,20 @@ namespace app {
virtual TabIcon getTabIcon() = 0; virtual TabIcon getTabIcon() = 0;
}; };
enum class DropTabResult {
IGNORE,
DOCKED_IN_OTHER_PLACE,
};
// Interface used to control notifications from the Tabs widget. // Interface used to control notifications from the Tabs widget.
class TabsDelegate { class TabsDelegate {
public: public:
virtual ~TabsDelegate() { } 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. // Called when the user selected the tab with the left mouse button.
virtual void onSelectTab(Tabs* tabs, TabView* tabView) = 0; virtual void onSelectTab(Tabs* tabs, TabView* tabView) = 0;
@ -59,7 +68,9 @@ namespace app {
// mouse just leave all tabs) // mouse just leave all tabs)
virtual void onMouseOverTab(Tabs* tabs, TabView* tabView) = 0; 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. // Tabs control. Used to show opened documents.

View File

@ -30,6 +30,7 @@ Workspace::Workspace()
: Widget(kGenericWidget) : Widget(kGenericWidget)
, m_tabsBar(nullptr) , m_tabsBar(nullptr)
, m_activeView(nullptr) , m_activeView(nullptr)
, m_dropPreview(false)
{ {
SkinTheme* theme = static_cast<SkinTheme*>(getTheme()); SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
setBgColor(theme->colors.workspace()); setBgColor(theme->colors.workspace());
@ -100,4 +101,58 @@ void Workspace::onPaint(PaintEvent& ev)
ev.getGraphics()->fillRect(getBgColor(), getClientBounds()); 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 } // namespace app

View File

@ -40,15 +40,23 @@ namespace app {
WorkspaceView* activeView(); WorkspaceView* activeView();
void setActiveView(WorkspaceView* view); 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; Signal0<void> ActiveViewChanged;
protected: protected:
void onPaint(ui::PaintEvent& ev) override; void onPaint(ui::PaintEvent& ev) override;
void onResize(ui::ResizeEvent& ev) override;
private: private:
Tabs* m_tabsBar; Tabs* m_tabsBar;
WorkspaceViews m_views; WorkspaceViews m_views;
WorkspaceView* m_activeView; WorkspaceView* m_activeView;
bool m_dropPreview;
gfx::Point m_dropPos;
}; };
} // namespace app } // namespace app