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;
}
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 void pushRecentProject(const HECL::SystemString& path) {}

View File

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

View File

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

View File

@ -5,9 +5,11 @@
namespace Specter
{
struct ISplitSpaceController;
class SplitView : public View
{
friend class RootView;
public:
class Resources
{
@ -24,6 +26,7 @@ public:
Vertical
};
private:
ISplitSpaceController* m_controller;
Axis m_axis;
float m_slide = 0.5;
void _setSplit(float slide);
@ -63,11 +66,17 @@ private:
VertexBufferBinding m_splitVertsBinding;
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);
void setSplit(float slide);
void setSplit(float split);
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 endDragSplit();
void moveDragSplit(const boo::SWindowCoord& coord);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);

View File

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

View File

@ -85,11 +85,10 @@ FileBrowser::FileBrowser(ViewResources& res, View& parentView, const std::string
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()));
m_split.m_view->setContentView(0, &m_left);
m_split.m_view->setContentView(1, &m_right);
m_split.m_view->setSplit(0.2);
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);
commitResources(res);
resized(rect, rect);
printf("New RootView: %p\n", this);
}
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)
{
if (m_hoverSplitDragView)
{
m_activeSplitDragView = true;
m_hoverSplitDragView->startDragSplit(coord);
return;
}
if (m_activeTextView && !m_activeTextView->subRect().coordInRect(coord))
setActiveTextView(nullptr);
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)
{
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)
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)
{
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)
m_activeDragView->mouseMove(coord);
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()));
if (tbPos != Toolbar::Position::None)
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)
@ -110,7 +109,6 @@ View* Space::setContentView(View* view)
View* ret = m_contentView.m_view;
m_contentView.m_view = view;
updateSize();
printf("Set Space: %p [%p]\n", this, view);
return ret;
}
@ -153,16 +151,16 @@ void Space::mouseMove(const boo::SWindowCoord& coord)
if (m_cornerView.m_view->m_flip)
{
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)
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1, coord);
}
else
{
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)
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0, coord);
}
}
else

View File

@ -2,6 +2,7 @@
#include "Specter/SplitView.hpp"
#include "Specter/RootView.hpp"
#include "Specter/ViewResources.hpp"
#include "Specter/Space.hpp"
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);
}
SplitView::SplitView(ViewResources& res, View& parentView, Axis axis, int clearanceA, int clearanceB)
: View(res, parentView), m_axis(axis), m_clearanceA(clearanceA), m_clearanceB(clearanceB)
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller,
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_splitVertsBinding.initTex(res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex);
commitResources(res);
printf("New SplitView: %p\n", this);
}
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_mouseIn = false;
updateSize();
printf("Set SplitView: %p [%d,%p]\n", this, slot, view);
return ret;
}
@ -65,6 +66,8 @@ void SplitView::_setSplit(float slide)
}
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)
@ -79,80 +82,59 @@ void SplitView::setAxis(Axis axis)
setSplit(m_slide);
}
bool SplitView::testSplitHover(const boo::SWindowCoord& coord)
{
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
return true;
}
else if (m_axis == Axis::Vertical)
{
int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
return true;
}
return false;
}
void SplitView::startDragSplit(const boo::SWindowCoord& coord)
{
m_dragging = true;
mouseMove(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::endDragSplit()
{
m_dragging = false;
}
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)
{
if (!rootView().m_spaceCornerHover)
{
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
{
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)
{
int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
{
if (button == boo::EMouseButton::Primary)
{
m_dragging = true;
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
}
else if (button == boo::EMouseButton::Secondary)
{
// TODO: Split menu
}
return;
}
}
}
m_views[0].mouseDown(coord, button, mod);
m_views[1].mouseDown(coord, button, 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[1].mouseUp(coord, button, mod);
}
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[1].mouseMove(coord);
}

View File

@ -2,7 +2,6 @@
#include "Specter/Toolbar.hpp"
#include "Specter/ViewResources.hpp"
#define TOOLBAR_GAUGE 28
#define TOOLBAR_PADDING 10
namespace Specter
@ -23,7 +22,7 @@ void Toolbar::Resources::init(boo::IGraphicsDataFactory* factory, const IThemeDa
Toolbar::Toolbar(ViewResources& res, View& parentView, Position 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_tbBlockBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Uniform, sizeof(ViewBlock), 1);