Add possibility to move tabs between different WorkspaceTabs widgets

This commit is contained in:
David Capello 2015-04-02 15:43:50 -03:00
parent 294ff0e4f6
commit e24c03f929
13 changed files with 156 additions and 43 deletions

View File

@ -51,8 +51,8 @@
#include "app/ui/keyboard_shortcuts.h"
#include "app/ui/main_window.h"
#include "app/ui/status_bar.h"
#include "app/ui/tabs.h"
#include "app/ui/toolbar.h"
#include "app/ui/workspace_tabs.h"
#include "app/ui_context.h"
#include "app/util/boundary.h"
#include "app/webserver.h"

View File

@ -13,7 +13,7 @@
#include "app/app.h"
#include "app/ui/main_window.h"
#include "app/ui/tabs.h"
#include "app/ui/workspace_tabs.h"
namespace app {

View File

@ -32,10 +32,10 @@
#include "app/ui/skin/skin_property.h"
#include "app/ui/skin/skin_theme.h"
#include "app/ui/status_bar.h"
#include "app/ui/tabs.h"
#include "app/ui/timeline.h"
#include "app/ui/toolbar.h"
#include "app/ui/workspace.h"
#include "app/ui/workspace_tabs.h"
#include "app/ui_context.h"
#include "ui/message.h"
#include "ui/splitter.h"
@ -60,13 +60,14 @@ MainWindow::MainWindow()
m_statusBar = new StatusBar();
m_colorBar = new ColorBar(colorBarPlaceholder()->getAlign());
m_toolBar = new ToolBar();
m_tabsBar = new Tabs(this);
m_tabsBar = new WorkspaceTabs(this);
m_workspace = new Workspace();
m_workspace->setTabsBar(m_tabsBar);
m_workspace->ActiveViewChanged.connect(&MainWindow::onActiveViewChange, this);
m_previewEditor = new PreviewEditorWindow();
m_timeline = new Timeline();
m_workspace->setTabsBar(m_tabsBar);
m_workspace->ActiveViewChanged.connect(&MainWindow::onActiveViewChange, this);
// configure all widgets to expansives
m_menuBar->setExpansive(true);
m_contextBar->setExpansive(true);
@ -299,7 +300,9 @@ void MainWindow::onMouseOverTab(Tabs* tabs, TabView* tabView)
void MainWindow::onFloatingTab(Tabs* tabs, TabView* tabView, const gfx::Point& pos)
{
m_workspace->setDropViewPreview(pos);
m_workspace->setDropViewPreview(pos,
dynamic_cast<WorkspaceView*>(tabView),
static_cast<WorkspaceTabs*>(tabs));
}
void MainWindow::onDockingTab(Tabs* tabs, TabView* tabView)

View File

@ -34,9 +34,9 @@ namespace app {
class Notifications;
class PreviewEditorWindow;
class StatusBar;
class Tabs;
class Timeline;
class Workspace;
class WorkspaceTabs;
class MainWindow : public app::gen::MainWindow
, public TabsDelegate {
@ -52,7 +52,7 @@ namespace app {
MainMenuBar* getMenuBar() { return m_menuBar; }
ContextBar* getContextBar() { return m_contextBar; }
Tabs* getTabsBar() { return m_tabsBar; }
WorkspaceTabs* getTabsBar() { return m_tabsBar; }
Timeline* getTimeline() { return m_timeline; }
Workspace* getWorkspace() { return m_workspace; }
PreviewEditorWindow* getPreviewEditor() { return m_previewEditor; }
@ -98,7 +98,7 @@ namespace app {
StatusBar* m_statusBar;
ColorBar* m_colorBar;
ui::Widget* m_toolBar;
Tabs* m_tabsBar;
WorkspaceTabs* m_tabsBar;
Mode m_mode;
Timeline* m_timeline;
Workspace* m_workspace;

View File

@ -36,7 +36,7 @@ namespace app {
using namespace app::skin;
using namespace ui;
static WidgetType tabs_type()
WidgetType Tabs::Type()
{
static WidgetType type = kGenericWidget;
if (type == kGenericWidget)
@ -45,7 +45,7 @@ static WidgetType tabs_type()
}
Tabs::Tabs(TabsDelegate* delegate)
: Widget(tabs_type())
: Widget(Tabs::Type())
, m_border(2)
, m_hot(nullptr)
, m_hotCloseButton(false)
@ -57,6 +57,7 @@ Tabs::Tabs(TabsDelegate* delegate)
, m_isDragging(false)
, m_floatingTab(nullptr)
, m_floatingOverlay(nullptr)
, m_dropNewTab(nullptr)
{
setDoubleBuffered(true);
initTheme();
@ -144,16 +145,31 @@ void Tabs::updateTabs()
tabWidth = MAX(4*ui::guiscale(), tabWidth);
}
double x = 0.0;
int i = 0;
if (m_dropNewTab)
m_dropNewIndex = -1;
for (auto& tab : m_list) {
if (tab == m_floatingTab)
if (tab == m_floatingTab) {
++i;
continue;
}
if (m_dropNewTab) {
int dropX = m_dropNewPos.x - getBounds().x;
if (dropX >= x-tabWidth/2 && dropX < x+tabWidth/2) {
x += tabWidth;
m_dropNewIndex = i;
}
}
tab->text = tab->view->getTabText();
tab->icon = tab->view->getTabIcon();
tab->x = int(x);
tab->width = int(x+tabWidth) - int(x);
x += tabWidth;
++i;
}
invalidate();
}
@ -220,6 +236,25 @@ void Tabs::setDockedStyle()
setBgColor(theme->colors.workspace());
}
void Tabs::setDropViewPreview(const gfx::Point& pos, TabView* view)
{
m_dropNewPos = pos;
m_dropNewTab = view;
resetOldPositions(animationTime());
updateTabs();
startAnimation(ANI_REORDER_TABS, ANI_REORDER_TABS_TICKS);
}
void Tabs::removeDropViewPreview()
{
m_dropNewTab = nullptr;
resetOldPositions(animationTime());
updateTabs();
startAnimation(ANI_REORDER_TABS, ANI_REORDER_TABS_TICKS);
}
bool Tabs::onProcessMessage(Message* msg)
{
switch (msg->type()) {
@ -718,7 +753,7 @@ void Tabs::stopDrag(DropTabResult result)
m_removedTab.reset(nullptr);
destroyFloatingTab();
ASSERT(tab);
//ASSERT(tab); // TODO check this state
if (tab)
removeTab(tab->view, false);
break;

View File

@ -105,6 +105,8 @@ namespace app {
};
public:
static ui::WidgetType Type();
Tabs(TabsDelegate* delegate);
~Tabs();
@ -121,6 +123,11 @@ namespace app {
void setDockedStyle();
// Drop TabViews into this Tabs widget
void setDropViewPreview(const gfx::Point& pos, TabView* view);
void removeDropViewPreview();
int getDropTabIndex() const { return m_dropNewIndex; }
protected:
bool onProcessMessage(ui::Message* msg) override;
void onPaint(ui::PaintEvent& ev) override;
@ -174,6 +181,11 @@ namespace app {
int m_dragTabIndex;
TabPtr m_floatingTab;
base::UniquePtr<ui::Overlay> m_floatingOverlay;
// Drop new tabs
gfx::Point m_dropNewPos;
TabView* m_dropNewTab;
int m_dropNewIndex;
};
} // namespace app

View File

@ -12,7 +12,7 @@
#include "app/ui/workspace.h"
#include "app/ui/skin/skin_theme.h"
#include "app/ui/tabs.h"
#include "app/ui/workspace_tabs.h"
#include "app/ui/workspace_view.h"
#include "base/remove_from_container.h"
#include "ui/paint_event.h"
@ -38,6 +38,7 @@ Workspace::Workspace()
, m_tabs(nullptr)
, m_activePanel(&m_mainPanel)
, m_dropPreviewPanel(nullptr)
, m_dropPreviewTabs(nullptr)
{
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
setBgColor(theme->colors.workspace());
@ -51,7 +52,7 @@ Workspace::~Workspace()
ASSERT(m_views.empty());
}
void Workspace::setTabsBar(Tabs* tabs)
void Workspace::setTabsBar(WorkspaceTabs* tabs)
{
m_tabs = tabs;
m_mainPanel.setTabsBar(tabs);
@ -59,11 +60,7 @@ void Workspace::setTabsBar(Tabs* tabs)
void Workspace::addView(WorkspaceView* view, int pos)
{
m_mainPanel.addView(view, pos);
m_activePanel = &m_mainPanel;
m_views.push_back(view);
setActiveView(view);
addViewToPanel(&m_mainPanel, view, pos);
}
void Workspace::removeView(WorkspaceView* view)
@ -122,31 +119,69 @@ void Workspace::onResize(ui::ResizeEvent& ev)
child->setBounds(rc);
}
void Workspace::setDropViewPreview(const gfx::Point& pos)
void Workspace::setDropViewPreview(const gfx::Point& pos,
WorkspaceView* view, WorkspaceTabs* tabs)
{
TabView* tabView = dynamic_cast<TabView*>(view);
WorkspaceTabs* newTabs = nullptr;
WorkspacePanel* panel = getPanelAt(pos);
if (!newTabs) {
newTabs = getTabsAt(pos);
// Drop preview is only to drop tabs from a different WorkspaceTabs.
if (newTabs == tabs)
newTabs = nullptr;
}
if (m_dropPreviewPanel && m_dropPreviewPanel != panel)
m_dropPreviewPanel->removeDropViewPreview();
if (m_dropPreviewTabs && m_dropPreviewTabs != newTabs)
m_dropPreviewTabs->removeDropViewPreview();
m_dropPreviewPanel = panel;
m_dropPreviewTabs = newTabs;
if (m_dropPreviewPanel)
m_dropPreviewPanel->setDropViewPreview(pos);
m_dropPreviewPanel->setDropViewPreview(pos, view);
if (m_dropPreviewTabs)
m_dropPreviewTabs->setDropViewPreview(pos, tabView);
}
void Workspace::removeDropViewPreview()
{
if (m_dropPreviewPanel)
m_dropPreviewPanel->removeDropViewPreview();
if (m_dropPreviewTabs)
m_dropPreviewTabs->removeDropViewPreview();
}
bool Workspace::dropViewAt(const gfx::Point& pos, WorkspaceView* view)
{
if (!m_dropPreviewPanel)
return false;
if (m_dropPreviewPanel)
return m_dropPreviewPanel->dropViewAt(pos, getViewPanel(view), view);
else if (m_dropPreviewTabs) {
WorkspacePanel* dropPanel = m_dropPreviewTabs->panel();
ASSERT(dropPanel);
return m_dropPreviewPanel->dropViewAt(pos, getViewPanel(view), view);
int pos = m_dropPreviewTabs->getDropTabIndex();
m_dropPreviewTabs->removeDropViewPreview();
removeView(view);
addViewToPanel(dropPanel, view, pos);
return true;
}
else
return false;
}
void Workspace::addViewToPanel(WorkspacePanel* panel, WorkspaceView* view, int pos)
{
panel->addView(view, pos);
m_activePanel = panel;
m_views.push_back(view);
setActiveView(view);
}
WorkspacePanel* Workspace::getViewPanel(WorkspaceView* view)
@ -173,4 +208,16 @@ WorkspacePanel* Workspace::getPanelAt(const gfx::Point& pos)
return nullptr;
}
WorkspaceTabs* Workspace::getTabsAt(const gfx::Point& pos)
{
Widget* widget = getManager()->pick(pos);
while (widget) {
if (widget->getType() == Tabs::Type())
return static_cast<WorkspaceTabs*>(widget);
widget = widget->getParent();
}
return nullptr;
}
} // namespace app

View File

@ -14,7 +14,7 @@
#include "ui/widget.h"
namespace app {
class Tabs;
class WorkspaceTabs;
class Workspace : public ui::Widget {
public:
@ -25,7 +25,7 @@ namespace app {
Workspace();
~Workspace();
void setTabsBar(Tabs* tabs);
void setTabsBar(WorkspaceTabs* tabs);
iterator begin() { return m_views.begin(); }
iterator end() { return m_views.end(); }
@ -42,7 +42,8 @@ namespace app {
void setMainPanelAsActive();
// Drop views into workspace
void setDropViewPreview(const gfx::Point& pos);
void setDropViewPreview(const gfx::Point& pos,
WorkspaceView* view, WorkspaceTabs* tabs);
void removeDropViewPreview();
// Returns true if the view was docked inside the workspace.
@ -55,17 +56,17 @@ namespace app {
void onResize(ui::ResizeEvent& ev) override;
private:
int calculateDropArea(const gfx::Point& pos) const;
int getDropThreshold() const;
void adjustTime(int& time, int flag);
void addViewToPanel(WorkspacePanel* panel, WorkspaceView* view, int pos);
WorkspacePanel* getViewPanel(WorkspaceView* view);
WorkspacePanel* getPanelAt(const gfx::Point& pos);
WorkspaceTabs* getTabsAt(const gfx::Point& pos);
WorkspacePanel m_mainPanel;
Tabs* m_tabs;
WorkspaceTabs* m_tabs;
WorkspaceViews m_views;
WorkspacePanel* m_activePanel;
WorkspacePanel* m_dropPreviewPanel;
WorkspaceTabs* m_dropPreviewTabs;
};
} // namespace app

View File

@ -12,7 +12,6 @@
#include "app/ui/workspace_panel.h"
#include "app/ui/skin/skin_theme.h"
#include "app/ui/tabs.h"
#include "app/ui/workspace.h"
#include "app/ui/workspace_tabs.h"
#include "app/ui/workspace_view.h"
@ -59,9 +58,10 @@ WorkspacePanel::~WorkspacePanel()
ASSERT(m_views.empty());
}
void WorkspacePanel::setTabsBar(Tabs* tabs)
void WorkspacePanel::setTabsBar(WorkspaceTabs* tabs)
{
m_tabs = tabs;
m_tabs->setPanel(this);
}
void WorkspacePanel::addView(WorkspaceView* view, int pos)
@ -181,7 +181,7 @@ void WorkspacePanel::adjustActiveViewBounds()
child->setBounds(rc);
}
void WorkspacePanel::setDropViewPreview(const gfx::Point& pos)
void WorkspacePanel::setDropViewPreview(const gfx::Point& pos, WorkspaceView* view)
{
int newDropArea = calculateDropArea(pos);
if (newDropArea != m_dropArea) {
@ -246,6 +246,7 @@ bool WorkspacePanel::dropViewAt(const gfx::Point& pos, WorkspacePanel* from, Wor
WorkspaceTabs* newTabs = new WorkspaceTabs(m_tabs->getDelegate());
WorkspacePanel* newPanel = new WorkspacePanel(SUB_PANEL);
newTabs->setDockedStyle();
newPanel->setTabsBar(newTabs);
newPanel->setExpansive(true);

View File

@ -18,8 +18,8 @@
#include <vector>
namespace app {
class Tabs;
class Workspace;
class WorkspaceTabs;
class WorkspacePanel : public ui::Widget
, public AnimatedWidget {
@ -41,7 +41,7 @@ namespace app {
WorkspacePanel(PanelType panelType);
~WorkspacePanel();
void setTabsBar(Tabs* tabs);
void setTabsBar(WorkspaceTabs* tabs);
iterator begin() { return m_views.begin(); }
iterator end() { return m_views.end(); }
@ -55,7 +55,7 @@ namespace app {
void setActiveView(WorkspaceView* view);
// Drop views into workspace
void setDropViewPreview(const gfx::Point& pos);
void setDropViewPreview(const gfx::Point& pos, WorkspaceView* view);
void removeDropViewPreview();
// Returns true if the view was docked inside the panel.
@ -75,7 +75,7 @@ namespace app {
Workspace* getWorkspace();
PanelType m_panelType;
Tabs* m_tabs;
WorkspaceTabs* m_tabs;
WorkspaceViews m_views;
WorkspaceView* m_activeView;
int m_dropArea;

View File

@ -17,12 +17,18 @@ using namespace ui;
WorkspaceTabs::WorkspaceTabs(TabsDelegate* tabsDelegate)
: Tabs(tabsDelegate)
, m_panel(nullptr)
{
setDockedStyle();
}
WorkspaceTabs::~WorkspaceTabs()
{
}
void WorkspaceTabs::setPanel(WorkspacePanel* panel)
{
ASSERT(!m_panel);
m_panel = panel;
}
} // namespace app

View File

@ -12,12 +12,20 @@
#include "app/ui/tabs.h"
namespace app {
class Tabs;
class WorkspacePanel;
class WorkspaceTabs : public Tabs {
public:
ui::WidgetType Type();
WorkspaceTabs(TabsDelegate* tabsDelegate);
~WorkspaceTabs();
WorkspacePanel* panel() const { return m_panel; }
void setPanel(WorkspacePanel* panel);
private:
WorkspacePanel* m_panel;
};
} // namespace app

View File

@ -20,9 +20,9 @@
#include "app/ui/editor/editor.h"
#include "app/ui/main_window.h"
#include "app/ui/preview_editor.h"
#include "app/ui/tabs.h"
#include "app/ui/timeline.h"
#include "app/ui/workspace.h"
#include "app/ui/workspace_tabs.h"
#include "app/ui_context.h"
#include "base/mutex.h"
#include "doc/sprite.h"