Much more reliable space splitting

This commit is contained in:
Jack Andersen 2016-01-11 14:44:54 -10:00
parent c38e4dd101
commit 54a5abc921
10 changed files with 145 additions and 75 deletions

View File

@ -21,7 +21,8 @@ public:
return vor; return vor;
} }
virtual void deferSpaceSplit(ISpaceController* split, SplitView::Axis axis, int thisSlot) {} virtual void deferSpaceSplit(ISpaceController* split, SplitView::Axis axis, int thisSlot,
const boo::SWindowCoord& coord) {}
virtual const std::vector<HECL::SystemString>* recentProjects() const {return nullptr;} virtual const std::vector<HECL::SystemString>* recentProjects() const {return nullptr;}
virtual void pushRecentProject(const HECL::SystemString& path) {} virtual void pushRecentProject(const HECL::SystemString& path) {}

View File

@ -27,6 +27,10 @@ class RootView : public View
ITextInputView* m_activeTextView = nullptr; ITextInputView* m_activeTextView = nullptr;
View* m_activeDragView = nullptr; View* m_activeDragView = nullptr;
SplitView* m_hoverSplitDragView = nullptr;
bool m_activeSplitDragView = false;
SplitView* recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const;
DeferredWindowEvents<RootView> m_events; DeferredWindowEvents<RootView> m_events;
public: public:
@ -79,6 +83,13 @@ public:
m_activeDragView = dragView; m_activeDragView = dragView;
} }
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord)
{
m_hoverSplitDragView = sv;
m_activeSplitDragView = true;
sv->startDragSplit(coord);
}
bool m_hSplitHover = false; bool m_hSplitHover = false;
void setHorizontalSplitHover(bool hover) void setHorizontalSplitHover(bool hover)
{ {

View File

@ -20,7 +20,7 @@ struct ISpaceController
struct ISplitSpaceController struct ISplitSpaceController
{ {
virtual SplitView* splitView()=0; virtual SplitView* splitView()=0;
virtual void setSplit(float split)=0; virtual void updateSplit(float split)=0;
}; };
class Space : public View class Space : public View

View File

@ -5,9 +5,11 @@
namespace Specter namespace Specter
{ {
struct ISplitSpaceController;
class SplitView : public View class SplitView : public View
{ {
friend class RootView;
public: public:
class Resources class Resources
{ {
@ -24,6 +26,7 @@ public:
Vertical Vertical
}; };
private: private:
ISplitSpaceController* m_controller;
Axis m_axis; Axis m_axis;
float m_slide = 0.5; float m_slide = 0.5;
void _setSplit(float slide); void _setSplit(float slide);
@ -63,11 +66,17 @@ private:
VertexBufferBinding m_splitVertsBinding; VertexBufferBinding m_splitVertsBinding;
public: public:
SplitView(ViewResources& res, View& parentView, Axis axis, int clearanceA=-1, int clearanceB=-1); SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller,
Axis axis, float split, int clearanceA=-1, int clearanceB=-1);
View* setContentView(int slot, View* view); View* setContentView(int slot, View* view);
void setSplit(float slide); void setSplit(float split);
void setAxis(Axis axis); void setAxis(Axis axis);
Axis axis() const {return m_axis;}
float split() const {return m_slide;}
bool testSplitHover(const boo::SWindowCoord& coord);
void startDragSplit(const boo::SWindowCoord& coord); void startDragSplit(const boo::SWindowCoord& coord);
void endDragSplit();
void moveDragSplit(const boo::SWindowCoord& coord);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);

View File

@ -5,6 +5,7 @@
namespace Specter namespace Specter
{ {
#define SPECTER_TOOLBAR_GAUGE 28
class Toolbar : public View class Toolbar : public View
{ {

View File

@ -85,11 +85,10 @@ FileBrowser::FileBrowser(ViewResources& res, View& parentView, const std::string
navigateToPath(initialPath); navigateToPath(initialPath);
m_split.m_view.reset(new SplitView(res, *this, SplitView::Axis::Vertical, m_split.m_view.reset(new SplitView(res, *this, nullptr, SplitView::Axis::Vertical, 0.2,
200 * res.pixelFactor(), 400 * res.pixelFactor())); 200 * res.pixelFactor(), 400 * res.pixelFactor()));
m_split.m_view->setContentView(0, &m_left); m_split.m_view->setContentView(0, &m_left);
m_split.m_view->setContentView(1, &m_right); m_split.m_view->setContentView(1, &m_right);
m_split.m_view->setSplit(0.2);
updateContentOpacity(0.0); updateContentOpacity(0.0);
} }

View File

@ -14,7 +14,6 @@ RootView::RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* wind
m_renderTex = res.m_factory->newRenderTexture(rect.size[0], rect.size[1], 1); m_renderTex = res.m_factory->newRenderTexture(rect.size[0], rect.size[1], 1);
commitResources(res); commitResources(res);
resized(rect, rect); resized(rect, rect);
printf("New RootView: %p\n", this);
} }
void RootView::destroyed() void RootView::destroyed()
@ -37,6 +36,13 @@ void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&)
void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
{ {
if (m_hoverSplitDragView)
{
m_activeSplitDragView = true;
m_hoverSplitDragView->startDragSplit(coord);
return;
}
if (m_activeTextView && !m_activeTextView->subRect().coordInRect(coord)) if (m_activeTextView && !m_activeTextView->subRect().coordInRect(coord))
setActiveTextView(nullptr); setActiveTextView(nullptr);
for (View* v : m_views) for (View* v : m_views)
@ -45,12 +51,76 @@ void RootView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton butto
void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void RootView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods)
{ {
if (m_activeSplitDragView && button == boo::EMouseButton::Primary)
{
m_activeSplitDragView = false;
m_hoverSplitDragView->endDragSplit();
m_spaceCornerHover = false;
m_hSplitHover = false;
m_vSplitHover = false;
_updateCursor();
}
for (View* v : m_views) for (View* v : m_views)
v->mouseUp(coord, button, mods); v->mouseUp(coord, button, mods);
} }
SplitView* RootView::recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const
{
if (sv->testSplitHover(coord))
return sv;
for (int i=0 ; i<2 ; ++i)
{
SplitView* child = dynamic_cast<SplitView*>(sv->m_views[i].m_view);
if (child)
{
SplitView* res = recursiveTestSplitHover(child, coord);
if (res)
return res;
}
}
return nullptr;
}
void RootView::mouseMove(const boo::SWindowCoord& coord) void RootView::mouseMove(const boo::SWindowCoord& coord)
{ {
if (m_activeSplitDragView)
{
m_hoverSplitDragView->moveDragSplit(coord);
m_spaceCornerHover = false;
if (m_hoverSplitDragView->axis() == SplitView::Axis::Horizontal)
setHorizontalSplitHover(true);
else
setVerticalSplitHover(true);
return;
}
m_hoverSplitDragView = nullptr;
if (!m_spaceCornerHover)
{
for (View* v : m_views)
{
SplitView* sv = dynamic_cast<SplitView*>(v);
if (sv)
sv = recursiveTestSplitHover(sv, coord);
if (sv)
{
if (sv->axis() == SplitView::Axis::Horizontal)
setHorizontalSplitHover(true);
else
setVerticalSplitHover(true);
m_hoverSplitDragView = sv;
break;
}
else
{
m_hSplitHover = false;
m_vSplitHover = false;
_updateCursor();
}
}
}
if (m_activeDragView) if (m_activeDragView)
m_activeDragView->mouseMove(coord); m_activeDragView->mouseMove(coord);
else else

View File

@ -25,7 +25,6 @@ Space::Space(ViewResources& res, View& parentView, ISpaceController& controller,
m_cornerView.m_view.reset(new CornerView(res, *this, spaceTriangleColor())); m_cornerView.m_view.reset(new CornerView(res, *this, spaceTriangleColor()));
if (tbPos != Toolbar::Position::None) if (tbPos != Toolbar::Position::None)
m_toolbar.m_view.reset(new Toolbar(res, *this, tbPos)); m_toolbar.m_view.reset(new Toolbar(res, *this, tbPos));
printf("New Space: %p\n", this);
} }
Space::CornerView::CornerView(ViewResources& res, Space& space, const Zeus::CColor& triColor) Space::CornerView::CornerView(ViewResources& res, Space& space, const Zeus::CColor& triColor)
@ -110,7 +109,6 @@ View* Space::setContentView(View* view)
View* ret = m_contentView.m_view; View* ret = m_contentView.m_view;
m_contentView.m_view = view; m_contentView.m_view = view;
updateSize(); updateSize();
printf("Set Space: %p [%p]\n", this, view);
return ret; return ret;
} }
@ -153,16 +151,16 @@ void Space::mouseMove(const boo::SWindowCoord& coord)
if (m_cornerView.m_view->m_flip) if (m_cornerView.m_view->m_flip)
{ {
if (coord.pixel[0] < m_cornerDragPoint[0] - CORNER_DRAG_THRESHOLD * pf) if (coord.pixel[0] < m_cornerDragPoint[0] - CORNER_DRAG_THRESHOLD * pf)
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 1); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 1, coord);
else if (coord.pixel[1] < m_cornerDragPoint[1] - CORNER_DRAG_THRESHOLD * pf) else if (coord.pixel[1] < m_cornerDragPoint[1] - CORNER_DRAG_THRESHOLD * pf)
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1, coord);
} }
else else
{ {
if (coord.pixel[0] > m_cornerDragPoint[0] + CORNER_DRAG_THRESHOLD * pf) if (coord.pixel[0] > m_cornerDragPoint[0] + CORNER_DRAG_THRESHOLD * pf)
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 0); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 0, coord);
else if (coord.pixel[1] > m_cornerDragPoint[1] + CORNER_DRAG_THRESHOLD * pf) else if (coord.pixel[1] > m_cornerDragPoint[1] + CORNER_DRAG_THRESHOLD * pf)
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0); rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0, coord);
} }
} }
else else

View File

@ -2,6 +2,7 @@
#include "Specter/SplitView.hpp" #include "Specter/SplitView.hpp"
#include "Specter/RootView.hpp" #include "Specter/RootView.hpp"
#include "Specter/ViewResources.hpp" #include "Specter/ViewResources.hpp"
#include "Specter/Space.hpp"
namespace Specter namespace Specter
{ {
@ -18,13 +19,14 @@ void SplitView::Resources::init(boo::IGraphicsDataFactory* factory, const ITheme
m_shadingTex = factory->newStaticTexture(3, 1, 1, boo::TextureFormat::RGBA8, tex, 12); m_shadingTex = factory->newStaticTexture(3, 1, 1, boo::TextureFormat::RGBA8, tex, 12);
} }
SplitView::SplitView(ViewResources& res, View& parentView, Axis axis, int clearanceA, int clearanceB) SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller,
: View(res, parentView), m_axis(axis), m_clearanceA(clearanceA), m_clearanceB(clearanceB) Axis axis, float split, int clearanceA, int clearanceB)
: View(res, parentView), m_controller(controller), m_axis(axis), m_slide(split),
m_clearanceA(clearanceA), m_clearanceB(clearanceB)
{ {
m_splitBlockBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Uniform, sizeof(ViewBlock), 1); m_splitBlockBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Uniform, sizeof(ViewBlock), 1);
m_splitVertsBinding.initTex(res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex); m_splitVertsBinding.initTex(res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex);
commitResources(res); commitResources(res);
printf("New SplitView: %p\n", this);
} }
View* SplitView::setContentView(int slot, View* view) View* SplitView::setContentView(int slot, View* view)
@ -36,7 +38,6 @@ View* SplitView::setContentView(int slot, View* view)
m_views[slot].m_mouseDown = 0; m_views[slot].m_mouseDown = 0;
m_views[slot].m_mouseIn = false; m_views[slot].m_mouseIn = false;
updateSize(); updateSize();
printf("Set SplitView: %p [%d,%p]\n", this, slot, view);
return ret; return ret;
} }
@ -65,6 +66,8 @@ void SplitView::_setSplit(float slide)
} }
m_slide = std::min(std::max(m_slide, 0.0f), 1.0f); m_slide = std::min(std::max(m_slide, 0.0f), 1.0f);
} }
if (m_controller)
m_controller->updateSplit(m_slide);
} }
void SplitView::setSplit(float slide) void SplitView::setSplit(float slide)
@ -79,80 +82,59 @@ void SplitView::setAxis(Axis axis)
setSplit(m_slide); setSplit(m_slide);
} }
void SplitView::startDragSplit(const boo::SWindowCoord& coord) bool SplitView::testSplitHover(const boo::SWindowCoord& coord)
{ {
m_dragging = true;
mouseMove(coord);
}
void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (!rootView().m_spaceCornerHover)
{
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal)
{ {
int slidePx = subRect().size[1] * m_slide; int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4) if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
{ return true;
if (button == boo::EMouseButton::Primary)
{
m_dragging = true;
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
}
else if (button == boo::EMouseButton::Secondary)
{
// TODO: Split menu
}
return;
}
} }
else if (m_axis == Axis::Vertical) else if (m_axis == Axis::Vertical)
{ {
int slidePx = subRect().size[0] * m_slide; int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4) if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
{ return true;
if (button == boo::EMouseButton::Primary) }
{ return false;
}
void SplitView::startDragSplit(const boo::SWindowCoord& coord)
{
m_dragging = true; m_dragging = true;
if (m_axis == Axis::Horizontal)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
else if (m_axis == Axis::Vertical)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0])); setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
} }
else if (button == boo::EMouseButton::Secondary)
{ void SplitView::endDragSplit()
// TODO: Split menu {
} m_dragging = false;
return; }
}
} void SplitView::moveDragSplit(const boo::SWindowCoord& coord)
} {
if (m_axis == Axis::Horizontal)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
else if (m_axis == Axis::Vertical)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
}
void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
m_views[0].mouseDown(coord, button, mod); m_views[0].mouseDown(coord, button, mod);
m_views[1].mouseDown(coord, button, mod); m_views[1].mouseDown(coord, button, mod);
} }
void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{ {
if (button == boo::EMouseButton::Primary)
m_dragging = false;
m_views[0].mouseUp(coord, button, mod); m_views[0].mouseUp(coord, button, mod);
m_views[1].mouseUp(coord, button, mod); m_views[1].mouseUp(coord, button, mod);
} }
void SplitView::mouseMove(const boo::SWindowCoord& coord) void SplitView::mouseMove(const boo::SWindowCoord& coord)
{ {
if (m_axis == Axis::Horizontal)
{
if (m_dragging)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
int slidePx = subRect().size[1] * m_slide;
rootView().setHorizontalSplitHover(abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4);
}
else if (m_axis == Axis::Vertical)
{
if (m_dragging)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
int slidePx = subRect().size[0] * m_slide;
rootView().setVerticalSplitHover(abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4);
}
m_views[0].mouseMove(coord); m_views[0].mouseMove(coord);
m_views[1].mouseMove(coord); m_views[1].mouseMove(coord);
} }

View File

@ -2,7 +2,6 @@
#include "Specter/Toolbar.hpp" #include "Specter/Toolbar.hpp"
#include "Specter/ViewResources.hpp" #include "Specter/ViewResources.hpp"
#define TOOLBAR_GAUGE 28
#define TOOLBAR_PADDING 10 #define TOOLBAR_PADDING 10
namespace Specter namespace Specter
@ -23,7 +22,7 @@ void Toolbar::Resources::init(boo::IGraphicsDataFactory* factory, const IThemeDa
Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos) Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos)
: View(res, parentView), m_tbPos(tbPos), : View(res, parentView), m_tbPos(tbPos),
m_nomHeight(res.pixelFactor() * TOOLBAR_GAUGE), m_nomHeight(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE),
m_padding(res.pixelFactor() * TOOLBAR_PADDING) m_padding(res.pixelFactor() * TOOLBAR_PADDING)
{ {
m_tbBlockBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Uniform, sizeof(ViewBlock), 1); m_tbBlockBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Uniform, sizeof(ViewBlock), 1);