TimeLine: add range outline and hot state

This is the first step to improve the copy/move of ranges in the timeline.
This commit is contained in:
David Capello 2014-03-30 12:53:57 -03:00
parent 875301cb82
commit 7ea7521f6a
3 changed files with 72 additions and 20 deletions

View File

@ -492,6 +492,16 @@
<background color="timeline_normal" part="timeline_padding_br" /> <background color="timeline_normal" part="timeline_padding_br" />
</style> </style>
<!-- timeline_range_outline -->
<style id="timeline_range_outline">
</style>
<style id="timeline_range_outline:active">
<background part="colorbar_border_hotfg" />
</style>
<style id="timeline_range_outline:hover">
<background part="colorbar_border_fg" />
</style>
</stylesheet> </stylesheet>
</skin> </skin>

View File

@ -102,6 +102,7 @@ static const char* kTimelinePaddingTr = "timeline_padding_tr";
static const char* kTimelinePaddingBl = "timeline_padding_bl"; static const char* kTimelinePaddingBl = "timeline_padding_bl";
static const char* kTimelinePaddingBr = "timeline_padding_br"; static const char* kTimelinePaddingBr = "timeline_padding_br";
static const char* kTimelineSelectedCelStyle = "timeline_selected_cel"; static const char* kTimelineSelectedCelStyle = "timeline_selected_cel";
static const char* kTimelineRangeOutlineStyle = "timeline_range_outline";
static const char* kTimelineActiveColor = "timeline_active"; static const char* kTimelineActiveColor = "timeline_active";
@ -118,7 +119,8 @@ enum {
A_PART_LAYER_EYE_ICON, A_PART_LAYER_EYE_ICON,
A_PART_LAYER_PADLOCK_ICON, A_PART_LAYER_PADLOCK_ICON,
A_PART_LAYER_TEXT, A_PART_LAYER_TEXT,
A_PART_CEL A_PART_CEL,
A_PART_RANGE_OUTLINE
}; };
Timeline::Timeline() Timeline::Timeline()
@ -143,6 +145,7 @@ Timeline::Timeline()
, m_timelinePaddingBlStyle(get_style(kTimelinePaddingBl)) , m_timelinePaddingBlStyle(get_style(kTimelinePaddingBl))
, m_timelinePaddingBrStyle(get_style(kTimelinePaddingBr)) , m_timelinePaddingBrStyle(get_style(kTimelinePaddingBr))
, m_timelineSelectedCelStyle(get_style(kTimelineSelectedCelStyle)) , m_timelineSelectedCelStyle(get_style(kTimelineSelectedCelStyle))
, m_timelineRangeOutlineStyle(get_style(kTimelineRangeOutlineStyle))
, m_context(UIContext::instance()) , m_context(UIContext::instance())
, m_editor(NULL) , m_editor(NULL)
, m_document(NULL) , m_document(NULL)
@ -312,7 +315,7 @@ bool Timeline::onProcessMessage(Message* msg)
m_state = STATE_MOVING_FRAME; m_state = STATE_MOVING_FRAME;
else { else {
m_state = STATE_SELECTING_FRAMES; m_state = STATE_SELECTING_FRAMES;
m_range.startRange(getLayerIndex(m_layer), m_clk_frame); m_range.startRange(getLayerIndex(m_layer), m_clk_frame, Range::Frames);
} }
} }
break; break;
@ -349,7 +352,7 @@ bool Timeline::onProcessMessage(Message* msg)
} }
if (startRange) if (startRange)
m_range.startRange(m_clk_layer, m_frame); m_range.startRange(m_clk_layer, m_frame, Range::Layers);
} }
break; break;
} }
@ -382,7 +385,7 @@ bool Timeline::onProcessMessage(Message* msg)
else { else {
m_state = STATE_SELECTING_CELS; m_state = STATE_SELECTING_CELS;
if (selectCel) if (selectCel)
m_range.startRange(m_clk_layer, m_clk_frame); m_range.startRange(m_clk_layer, m_clk_frame, Range::Cels);
invalidate(); invalidate();
} }
break; break;
@ -521,6 +524,12 @@ bool Timeline::onProcessMessage(Message* msg)
else { else {
if (hot_layer >= (int)m_layers.size()) hot_layer = -1; if (hot_layer >= (int)m_layers.size()) hot_layer = -1;
if (hot_frame > m_sprite->getLastFrame()) hot_frame = FrameNumber(-1); if (hot_frame > m_sprite->getLastFrame()) hot_frame = FrameNumber(-1);
gfx::Rect outline = getPartBounds(A_PART_RANGE_OUTLINE);
if (outline.contains(mousePos) &&
!gfx::Rect(outline).shrink(4*jguiscale()).contains(mousePos)) {
hot_part = A_PART_RANGE_OUTLINE;
}
} }
// Set the new 'hot' thing. // Set the new 'hot' thing.
@ -669,7 +678,7 @@ bool Timeline::onProcessMessage(Message* msg)
regenerateLayers(); regenerateLayers();
m_range.startRange(getLayerIndex(firstLayer), m_frame); m_range.startRange(getLayerIndex(firstLayer), m_frame, m_range.type());
m_range.endRange(getLayerIndex(lastLayer), m_frame); m_range.endRange(getLayerIndex(lastLayer), m_frame);
} }
catch (LockedDocumentException& e) { catch (LockedDocumentException& e) {
@ -748,11 +757,6 @@ bool Timeline::onProcessMessage(Message* msg)
} }
} }
// Disable range if we selected only one cel.
if (m_range.layerBegin() == m_range.layerEnd() &&
m_range.frameBegin() == m_range.frameEnd())
m_range.disableRange();
// Clean the clicked-part & redraw the hot-part. // Clean the clicked-part & redraw the hot-part.
cleanClk(); cleanClk();
@ -942,6 +946,7 @@ void Timeline::onPaint(ui::PaintEvent& ev)
} }
drawPaddings(g); drawPaddings(g);
drawRangeOutline(g);
} }
catch (const LockedDocumentException&) { catch (const LockedDocumentException&) {
noDoc = true; noDoc = true;
@ -1099,6 +1104,9 @@ void Timeline::setCursor(int x, int y)
|| m_state == STATE_MOVING_ONIONSKIN_RANGE_RIGHT) { || m_state == STATE_MOVING_ONIONSKIN_RANGE_RIGHT) {
jmouse_set_cursor(kSizeRCursor); jmouse_set_cursor(kSizeRCursor);
} }
else if (m_hot_part == A_PART_RANGE_OUTLINE) {
jmouse_set_cursor(kMoveCursor);
}
else { else {
jmouse_set_cursor(kArrowCursor); jmouse_set_cursor(kArrowCursor);
} }
@ -1270,6 +1278,17 @@ void Timeline::drawCel(ui::Graphics* g, int layer_index, FrameNumber frame, Cel*
drawPart(g, bounds, NULL, style, is_active, is_hover); drawPart(g, bounds, NULL, style, is_active, is_hover);
} }
void Timeline::drawRangeOutline(ui::Graphics* g)
{
gfx::Rect bounds = getPartBounds(A_PART_RANGE_OUTLINE);
Style::State state;
if (m_range.enabled()) state += Style::active();
if (m_hot_part == A_PART_RANGE_OUTLINE) state += Style::hover();
m_timelineRangeOutlineStyle->paint(g, bounds, NULL, state);
}
void Timeline::drawPaddings(ui::Graphics* g) void Timeline::drawPaddings(ui::Graphics* g)
{ {
gfx::Rect client = getClientBounds(); gfx::Rect client = getClientBounds();
@ -1425,6 +1444,24 @@ gfx::Rect Timeline::getPartBounds(int part, int layer, FrameNumber frame) const
LAYSIZE); LAYSIZE);
} }
break; break;
case A_PART_RANGE_OUTLINE:
switch (m_range.type()) {
case Range::None: break; // Return empty rectangle
case Range::Cels:
return
getPartBounds(A_PART_CEL, m_range.layerBegin(), m_range.frameBegin()).createUnion(
getPartBounds(A_PART_CEL, m_range.layerEnd(), m_range.frameEnd())).enlarge(2*jguiscale());
case Range::Frames:
return
getPartBounds(A_PART_HEADER_FRAME, 0, m_range.frameBegin()).createUnion(
getPartBounds(A_PART_HEADER_FRAME, 0, m_range.frameEnd()));
case Range::Layers:
return
getPartBounds(A_PART_LAYER, m_range.layerBegin()).createUnion(
getPartBounds(A_PART_LAYER, m_range.layerEnd()));
}
break;
} }
return gfx::Rect(); return gfx::Rect();
@ -1658,28 +1695,28 @@ bool Timeline::isFrameActive(FrameNumber frame) const
return m_range.inRange(frame); return m_range.inRange(frame);
} }
void Timeline::Range::startRange(int layer, FrameNumber frame) void Timeline::Range::startRange(int layer, FrameNumber frame, Type type)
{ {
m_enabled = true; m_type = type;
m_layerBegin = m_layerEnd = layer; m_layerBegin = m_layerEnd = layer;
m_frameBegin = m_frameEnd = frame; m_frameBegin = m_frameEnd = frame;
} }
void Timeline::Range::endRange(int layer, FrameNumber frame) void Timeline::Range::endRange(int layer, FrameNumber frame)
{ {
ASSERT(m_enabled); ASSERT(enabled());
m_layerEnd = layer; m_layerEnd = layer;
m_frameEnd = frame; m_frameEnd = frame;
} }
void Timeline::Range::disableRange() void Timeline::Range::disableRange()
{ {
m_enabled = false; m_type = None;
} }
bool Timeline::Range::inRange(int layer) const bool Timeline::Range::inRange(int layer) const
{ {
if (m_enabled) if (enabled())
return (layer >= layerBegin() && layer <= layerEnd()); return (layer >= layerBegin() && layer <= layerEnd());
else else
return false; return false;
@ -1687,7 +1724,7 @@ bool Timeline::Range::inRange(int layer) const
bool Timeline::Range::inRange(FrameNumber frame) const bool Timeline::Range::inRange(FrameNumber frame) const
{ {
if (m_enabled) if (enabled())
return (frame >= frameBegin() && frame <= frameEnd()); return (frame >= frameBegin() && frame <= frameEnd());
else else
return false; return false;

View File

@ -67,9 +67,12 @@ namespace app {
}; };
struct Range { struct Range {
Range() : m_enabled(false) { } enum Type { None, Cels, Frames, Layers };
bool enabled() const { return m_enabled; } Range() : m_type(None) { }
Type type() const { return m_type; }
bool enabled() const { return m_type != None; }
int layerBegin() const { return MIN(m_layerBegin, m_layerEnd); } int layerBegin() const { return MIN(m_layerBegin, m_layerEnd); }
int layerEnd() const { return MAX(m_layerBegin, m_layerEnd); } int layerEnd() const { return MAX(m_layerBegin, m_layerEnd); }
FrameNumber frameBegin() const { return MIN(m_frameBegin, m_frameEnd); } FrameNumber frameBegin() const { return MIN(m_frameBegin, m_frameEnd); }
@ -79,12 +82,12 @@ namespace app {
bool inRange(FrameNumber frame) const; bool inRange(FrameNumber frame) const;
bool inRange(int layer, FrameNumber frame) const; bool inRange(int layer, FrameNumber frame) const;
void startRange(int layer, FrameNumber frame); void startRange(int layer, FrameNumber frame, Type type);
void endRange(int layer, FrameNumber frame); void endRange(int layer, FrameNumber frame);
void disableRange(); void disableRange();
private: private:
bool m_enabled; Type m_type;
int m_layerBegin; int m_layerBegin;
int m_layerEnd; int m_layerEnd;
FrameNumber m_frameBegin; FrameNumber m_frameBegin;
@ -142,6 +145,7 @@ namespace app {
void drawHeaderFrame(ui::Graphics* g, FrameNumber frame); void drawHeaderFrame(ui::Graphics* g, FrameNumber frame);
void drawLayer(ui::Graphics* g, int layer_index); void drawLayer(ui::Graphics* g, int layer_index);
void drawCel(ui::Graphics* g, int layer_index, FrameNumber frame, Cel* cel); void drawCel(ui::Graphics* g, int layer_index, FrameNumber frame, Cel* cel);
void drawRangeOutline(ui::Graphics* g);
void drawPaddings(ui::Graphics* g); void drawPaddings(ui::Graphics* g);
bool drawPart(ui::Graphics* g, int part, int layer, FrameNumber frame); bool drawPart(ui::Graphics* g, int part, int layer, FrameNumber frame);
gfx::Rect getLayerHeadersBounds() const; gfx::Rect getLayerHeadersBounds() const;
@ -182,6 +186,7 @@ namespace app {
skin::Style* m_timelinePaddingBlStyle; skin::Style* m_timelinePaddingBlStyle;
skin::Style* m_timelinePaddingBrStyle; skin::Style* m_timelinePaddingBrStyle;
skin::Style* m_timelineSelectedCelStyle; skin::Style* m_timelineSelectedCelStyle;
skin::Style* m_timelineRangeOutlineStyle;
Context* m_context; Context* m_context;
Editor* m_editor; Editor* m_editor;
Document* m_document; Document* m_document;