clean up VST preset debug output
[ardour2.git] / gtk2_ardour / time_axis_view_item.cc
blob0a33b4c205f2a41808eb213d7519ba8d4f26c6e6
1 /*
2 Copyright (C) 2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <pbd/error.h>
21 #include <pbd/stacktrace.h>
23 #include <ardour/types.h>
24 #include <ardour/ardour.h>
26 #include <gtkmm2ext/utils.h>
28 #include "public_editor.h"
29 #include "time_axis_view_item.h"
30 #include "time_axis_view.h"
31 #include "simplerect.h"
32 #include "utils.h"
33 #include "canvas_impl.h"
34 #include "rgb_macros.h"
35 #include "ardour_ui.h"
37 #include "i18n.h"
39 using namespace std;
40 using namespace Editing;
41 using namespace Glib;
42 using namespace PBD;
44 //------------------------------------------------------------------------------
45 /** Initialize const static memeber data */
47 Pango::FontDescription* TimeAxisViewItem::NAME_FONT = 0;
48 bool TimeAxisViewItem::have_name_font = false;
49 const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;
50 const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ;
52 double TimeAxisViewItem::NAME_Y_OFFSET;
53 double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE;
54 double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH;
57 //---------------------------------------------------------------------------------------//
58 // Constructor / Desctructor
60 /**
61 * Constructs a new TimeAxisViewItem.
63 * @param it_name the unique name/Id of this item
64 * @param parant the parent canvas group
65 * @param tv the TimeAxisView we are going to be added to
66 * @param spu samples per unit
67 * @param base_color
68 * @param start the start point of this item
69 * @param duration the duration of this item
71 TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color& base_color,
72 nframes_t start, nframes_t duration, bool recording,
73 Visibility vis)
74 : trackview (tv), _recregion(recording)
76 if (!have_name_font) {
78 /* first constructed item sets up font info */
80 NAME_FONT = get_font_for_style (N_("TimeAxisViewItemName"));
82 Gtk::Window win;
83 Gtk::Label foo;
84 win.add (foo);
86 Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (X_("Hg")); /* ascender + descender */
87 int width;
88 int height;
90 layout->set_font_description (*NAME_FONT);
91 Gtkmm2ext::get_ink_pixel_size (layout, width, height);
93 NAME_Y_OFFSET = height + 6;
94 NAME_HIGHLIGHT_SIZE = height + 6;
95 NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 2;
97 have_name_font = true;
100 group = new ArdourCanvas::Group (parent);
102 init (it_name, spu, base_color, start, duration, vis);
106 TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
107 : trackview (other.trackview)
110 Gdk::Color c;
111 int r,g,b,a;
113 UINT_TO_RGBA (other.fill_color, &r, &g, &b, &a);
114 c.set_rgb_p (r/255.0, g/255.0, b/255.0);
116 /* share the other's parent, but still create a new group */
118 Gnome::Canvas::Group* parent = other.group->property_parent();
120 group = new ArdourCanvas::Group (*parent);
122 init (other.item_name, other.samples_per_unit, c, other.frame_position, other.item_duration, other.visibility);
126 void
127 TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_color, nframes_t start, nframes_t duration, Visibility vis)
129 item_name = it_name ;
130 name_text_width = ::pixel_width (it_name, *NAME_FONT);
131 last_name_text_width = 0;
132 samples_per_unit = spu ;
133 should_show_selection = true;
134 frame_position = start ;
135 item_duration = duration ;
136 name_connected = false;
137 fill_opacity = 0;
138 position_locked = false ;
139 max_item_duration = ARDOUR::max_frames;
140 min_item_duration = 0 ;
141 show_vestigial = true;
142 visibility = vis;
143 _sensitive = true;
145 if (duration == 0) {
146 warning << "Time Axis Item Duration == 0" << endl ;
149 vestigial_frame = new ArdourCanvas::SimpleRect (*group);
150 vestigial_frame->property_x1() = (double) 0.0;
151 vestigial_frame->property_y1() = (double) 1.0;
152 vestigial_frame->property_x2() = (double) 2.0;
153 vestigial_frame->property_y2() = (double) trackview.current_height();
154 vestigial_frame->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_VestigialFrame.get();
155 vestigial_frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_VestigialFrame.get();
156 vestigial_frame->hide ();
158 if (visibility & ShowFrame) {
159 frame = new ArdourCanvas::SimpleRect (*group);
160 frame->property_x1() = (double) 0.0;
161 frame->property_y1() = (double) 1.0;
162 frame->property_x2() = (double) trackview.editor.frame_to_pixel(duration);
163 frame->property_y2() = (double) trackview.current_height();
164 frame->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get();
166 /* by default draw all 4 edges */
168 uint32_t outline_what = 0x1|0x2|0x4|0x8;
170 if (visibility & HideFrameLeft) {
171 outline_what &= ~(0x1);
174 if (visibility & HideFrameRight) {
175 outline_what &= ~(0x2);
178 if (visibility & HideFrameTB) {
179 outline_what &= ~(0x4 | 0x8);
182 frame->property_outline_what() = outline_what;
184 } else {
185 frame = 0;
188 if (visibility & ShowNameHighlight) {
189 name_highlight = new ArdourCanvas::SimpleRect (*group);
190 if (visibility & FullWidthNameHighlight) {
191 name_highlight->property_x1() = (double) 0.0;
192 name_highlight->property_x2() = (double) (trackview.editor.frame_to_pixel(item_duration));
193 } else {
194 name_highlight->property_x1() = (double) 1.0;
195 name_highlight->property_x2() = (double) (trackview.editor.frame_to_pixel(item_duration)) - 1;
197 name_highlight->property_y1() = (double) (trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE);
198 name_highlight->property_y2() = (double) (trackview.current_height() - 1);
200 name_highlight->set_data ("timeaxisviewitem", this);
202 } else {
203 name_highlight = 0;
206 /* create our grab handles used for trimming/duration etc */
208 if (visibility & ShowHandles) {
209 frame_handle_start = new ArdourCanvas::SimpleRect (*group);
210 frame_handle_start->property_x1() = (double) 0.0;
211 frame_handle_start->property_x2() = (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH;
212 frame_handle_start->property_y1() = (double) 1.0;
213 frame_handle_start->property_y2() = (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH+1;
214 frame_handle_start->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_FrameHandle.get();
216 frame_handle_end = new ArdourCanvas::SimpleRect (*group);
217 frame_handle_end->property_x1() = (double) (trackview.editor.frame_to_pixel(get_duration())) - (TimeAxisViewItem::GRAB_HANDLE_LENGTH);
218 frame_handle_end->property_x2() = (double) trackview.editor.frame_to_pixel(get_duration());
219 frame_handle_end->property_y1() = (double) 1;
220 frame_handle_end->property_y2() = (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH + 1;
221 frame_handle_end->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_FrameHandle.get();
223 } else {
224 frame_handle_start = 0;
225 frame_handle_end = 0;
228 if (visibility & ShowNameText) {
229 name_text = new ArdourCanvas::Text (*group);
230 name_text->property_x() = (double) TimeAxisViewItem::NAME_X_OFFSET;
231 /* trackview.current_height() is the bottom of the trackview. subtract 1 to get back to the bottom of the highlight,
232 then NAME_Y_OFFSET to position the text in the vertical center of the highlight
234 name_text->property_y() = (double) trackview.current_height() - 1.0 - TimeAxisViewItem::NAME_Y_OFFSET;
235 name_text->property_font_desc() = *NAME_FONT;
236 name_text->property_anchor() = Gtk::ANCHOR_NW;
238 name_text->set_data ("timeaxisviewitem", this);
240 } else {
241 name_text = 0;
244 set_color (base_color) ;
246 set_duration (item_duration, this) ;
247 set_position (start, this) ;
251 * Destructor
253 TimeAxisViewItem::~TimeAxisViewItem()
255 delete group;
259 //---------------------------------------------------------------------------------------//
260 // Position and duration Accessors/Mutators
263 * Set the position of this item upon the timeline to the specified value
265 * @param pos the new position
266 * @param src the identity of the object that initiated the change
267 * @return true if the position change was a success, false otherwise
269 bool
270 TimeAxisViewItem::set_position(nframes_t pos, void* src, double* delta)
272 if (position_locked) {
273 return false;
276 frame_position = pos;
278 /* This sucks. The GnomeCanvas version I am using
279 doesn't correctly implement gnome_canvas_group_set_arg(),
280 so that simply setting the "x" arg of the group
281 fails to move the group. Instead, we have to
282 use gnome_canvas_item_move(), which does the right
283 thing. I see that in GNOME CVS, the current (Sept 2001)
284 version of GNOME Canvas rectifies this issue cleanly.
287 double old_unit_pos ;
288 double new_unit_pos = pos / samples_per_unit ;
290 old_unit_pos = group->property_x();
292 if (new_unit_pos != old_unit_pos) {
293 group->move (new_unit_pos - old_unit_pos, 0.0);
296 if (delta) {
297 (*delta) = new_unit_pos - old_unit_pos;
300 PositionChanged (frame_position, src) ; /* EMIT_SIGNAL */
302 return true;
306 * Return the position of this item upon the timeline
308 * @return the position of this item
310 nframes_t
311 TimeAxisViewItem::get_position() const
313 return frame_position;
317 * Sets the duration of this item
319 * @param dur the new duration of this item
320 * @param src the identity of the object that initiated the change
321 * @return true if the duration change was succesful, false otherwise
323 bool
324 TimeAxisViewItem::set_duration (nframes_t dur, void* src)
326 if ((dur > max_item_duration) || (dur < min_item_duration)) {
327 warning << string_compose (_("new duration %1 frames is out of bounds for %2"), get_item_name(), dur)
328 << endmsg;
329 return false;
332 if (dur == 0) {
333 group->hide();
336 item_duration = dur;
338 reset_width_dependent_items (trackview.editor.frame_to_pixel (dur));
340 DurationChanged (dur, src) ; /* EMIT_SIGNAL */
341 return true;
345 * Returns the duration of this item
348 nframes_t
349 TimeAxisViewItem::get_duration() const
351 return (item_duration);
355 * Sets the maximum duration that this item make have.
357 * @param dur the new maximum duration
358 * @param src the identity of the object that initiated the change
360 void
361 TimeAxisViewItem::set_max_duration(nframes_t dur, void* src)
363 max_item_duration = dur ;
364 MaxDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
368 * Returns the maxmimum duration that this item may be set to
370 * @return the maximum duration that this item may be set to
372 nframes_t
373 TimeAxisViewItem::get_max_duration() const
375 return (max_item_duration) ;
379 * Sets the minimu duration that this item may be set to
381 * @param the minimum duration that this item may be set to
382 * @param src the identity of the object that initiated the change
384 void
385 TimeAxisViewItem::set_min_duration(nframes_t dur, void* src)
387 min_item_duration = dur ;
388 MinDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
392 * Returns the minimum duration that this item mey be set to
394 * @return the nimum duration that this item mey be set to
396 nframes_t
397 TimeAxisViewItem::get_min_duration() const
399 return(min_item_duration) ;
403 * Sets whether the position of this Item is locked to its current position
404 * Locked items cannot be moved until the item is unlocked again.
406 * @param yn set to true to lock this item to its current position
407 * @param src the identity of the object that initiated the change
409 void
410 TimeAxisViewItem::set_position_locked(bool yn, void* src)
412 position_locked = yn ;
413 set_trim_handle_colors() ;
414 PositionLockChanged (position_locked, src); /* EMIT_SIGNAL */
418 * Returns whether this item is locked to its current position
420 * @return true if this item is locked to its current posotion
421 * false otherwise
423 bool
424 TimeAxisViewItem::get_position_locked() const
426 return (position_locked);
430 * Sets whether the Maximum Duration constraint is active and should be enforced
432 * @param active set true to enforce the max duration constraint
433 * @param src the identity of the object that initiated the change
435 void
436 TimeAxisViewItem::set_max_duration_active(bool active, void* src)
438 max_duration_active = active ;
442 * Returns whether the Maximum Duration constraint is active and should be enforced
444 * @return true if the maximum duration constraint is active, false otherwise
446 bool
447 TimeAxisViewItem::get_max_duration_active() const
449 return(max_duration_active) ;
453 * Sets whether the Minimum Duration constraint is active and should be enforced
455 * @param active set true to enforce the min duration constraint
456 * @param src the identity of the object that initiated the change
458 void
459 TimeAxisViewItem::set_min_duration_active(bool active, void* src)
461 min_duration_active = active ;
465 * Returns whether the Maximum Duration constraint is active and should be enforced
467 * @return true if the maximum duration constraint is active, false otherwise
469 bool
470 TimeAxisViewItem::get_min_duration_active() const
472 return(min_duration_active) ;
475 //---------------------------------------------------------------------------------------//
476 // Name/Id Accessors/Mutators
479 * Set the name/Id of this item.
481 * @param new_name the new name of this item
482 * @param src the identity of the object that initiated the change
484 void
485 TimeAxisViewItem::set_item_name(std::string new_name, void* src)
487 if (new_name != item_name) {
488 std::string temp_name = item_name ;
489 item_name = new_name ;
490 name_text_width = ::pixel_width (new_name, *NAME_FONT);
491 NameChanged (item_name, temp_name, src) ; /* EMIT_SIGNAL */
496 * Returns the name/id of this item
498 * @return the name/id of this item
500 std::string
501 TimeAxisViewItem::get_item_name() const
503 return(item_name) ;
506 //---------------------------------------------------------------------------------------//
507 // Selection Methods
510 * Set to true to indicate that this item is currently selected
512 * @param yn true if this item is currently selected
513 * @param src the identity of the object that initiated the change
515 void
516 TimeAxisViewItem::set_selected(bool yn)
518 if (_selected != yn) {
519 Selectable::set_selected (yn);
520 set_frame_color ();
524 void
525 TimeAxisViewItem::set_should_show_selection (bool yn)
527 if (should_show_selection != yn) {
528 should_show_selection = yn;
529 set_frame_color ();
533 //---------------------------------------------------------------------------------------//
534 // Parent Componenet Methods
537 * Returns the TimeAxisView that this item is upon
539 * @return the timeAxisView that this item is placed upon
541 TimeAxisView&
542 TimeAxisViewItem::get_time_axis_view()
544 return trackview;
546 //---------------------------------------------------------------------------------------//
547 // ui methods & data
550 * Sets the displayed item text
551 * This item is the visual text name displayed on the canvas item, this can be different to the name of the item
553 * @param new_name the new name text to display
555 void
556 TimeAxisViewItem::set_name_text(const ustring& new_name)
558 if (name_text) {
559 name_text->property_text() = new_name;
560 name_text_width = pixel_width (new_name, *NAME_FONT);
561 name_text_size_cache.clear ();
566 * Set the height of this item
568 * @param h the new height
570 void
571 TimeAxisViewItem::set_height (double height)
573 if (name_highlight) {
574 if (height < NAME_HIGHLIGHT_THRESH) {
575 name_highlight->hide();
576 if (name_text) {
577 name_text->hide();
579 } else {
580 name_highlight->show();
581 if (name_text) {
582 name_text->show();
586 if (height > NAME_HIGHLIGHT_SIZE) {
587 name_highlight->property_y1() = (double) height+1 - NAME_HIGHLIGHT_SIZE;
588 name_highlight->property_y2() = (double) height;
589 } else {
590 /* it gets hidden now anyway */
591 //name_highlight->property_y1() = (double) 1.0;
592 //name_highlight->property_y2() = (double) height;
596 if (name_text) {
597 name_text->property_y() = height+1 - NAME_Y_OFFSET;
598 if (height < NAME_HIGHLIGHT_THRESH) {
599 name_text->property_fill_color_rgba() = fill_color;
600 } else {
601 name_text->property_fill_color_rgba() = label_color;
605 if (frame) {
606 frame->property_y2() = height+1;
609 vestigial_frame->property_y2() = height+1;
615 void
616 TimeAxisViewItem::set_color(Gdk::Color& base_color)
618 compute_colors (base_color);
619 set_colors ();
625 ArdourCanvas::Item*
626 TimeAxisViewItem::get_canvas_frame()
628 return(frame) ;
634 ArdourCanvas::Group*
635 TimeAxisViewItem::get_canvas_group()
637 return (group) ;
643 ArdourCanvas::Item*
644 TimeAxisViewItem::get_name_highlight()
646 return (name_highlight) ;
652 ArdourCanvas::Text*
653 TimeAxisViewItem::get_name_text()
655 return (name_text) ;
659 * Calculates some contrasting color for displaying various parts of this item, based upon the base color
661 * @param color the base color of the item
663 void
664 TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
666 unsigned char radius ;
667 char minor_shift ;
669 unsigned char r,g,b ;
671 /* FILL: this is simple */
672 r = base_color.get_red()/256 ;
673 g = base_color.get_green()/256 ;
674 b = base_color.get_blue()/256 ;
675 fill_color = RGBA_TO_UINT(r,g,b,255) ;
677 /* for minor colors:
678 if the overall saturation is strong, make the minor colors light.
679 if its weak, make them dark.
681 we do this by moving an equal distance to the other side of the
682 central circle in the color wheel from where we started.
685 radius = (unsigned char) rint (floor (sqrt (static_cast<double>(r*r + g*g + b+b))/3.0f)) ;
686 minor_shift = 125 - radius ;
688 /* LABEL: rotate around color wheel by 120 degrees anti-clockwise */
690 r = base_color.get_red()/256;
691 g = base_color.get_green()/256;
692 b = base_color.get_blue()/256;
694 if (r > b)
696 if (r > g)
698 /* red sector => green */
699 swap (r,g);
701 else
703 /* green sector => blue */
704 swap (g,b);
707 else
709 if (b > g)
711 /* blue sector => red */
712 swap (b,r);
714 else
716 /* green sector => blue */
717 swap (g,b);
721 r += minor_shift;
722 b += minor_shift;
723 g += minor_shift;
725 label_color = RGBA_TO_UINT(r,g,b,255);
726 r = (base_color.get_red()/256) + 127 ;
727 g = (base_color.get_green()/256) + 127 ;
728 b = (base_color.get_blue()/256) + 127 ;
730 label_color = RGBA_TO_UINT(r,g,b,255);
732 /* XXX can we do better than this ? */
733 /* We're trying ;) */
734 /* NUKECOLORS */
736 //frame_color_r = 192;
737 //frame_color_g = 192;
738 //frame_color_b = 194;
740 //selected_frame_color_r = 182;
741 //selected_frame_color_g = 145;
742 //selected_frame_color_b = 168;
744 //handle_color_r = 25 ;
745 //handle_color_g = 0 ;
746 //handle_color_b = 255 ;
747 //lock_handle_color_r = 235 ;
748 //lock_handle_color_g = 16;
749 //lock_handle_color_b = 16;
753 * Convenience method to set the various canvas item colors
755 void
756 TimeAxisViewItem::set_colors()
758 set_frame_color() ;
759 if (name_text) {
760 double height = NAME_HIGHLIGHT_THRESH;
762 if (frame) {
763 height = frame->property_y2();
766 if (height < NAME_HIGHLIGHT_THRESH) {
767 name_text->property_fill_color_rgba() = fill_color;
769 else {
770 name_text->property_fill_color_rgba() = label_color;
774 if (name_highlight) {
775 name_highlight->property_fill_color_rgba() = fill_color;
776 name_highlight->property_outline_color_rgba() = fill_color;
778 set_trim_handle_colors() ;
782 * Sets the frame color depending on whether this item is selected
784 void
785 TimeAxisViewItem::set_frame_color()
787 if (frame) {
788 uint32_t r,g,b,a;
790 if (_selected && should_show_selection) {
791 UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get(), &r, &g, &b, &a);
792 frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);// Lets still use the theme's opacity value if Opaque is not set
793 } else {
794 if (_recregion) {
795 UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_RecordingRect.get(), &r, &g, &b, &a);
796 frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, a);
797 } else {
798 UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a);
799 frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);
806 * Sets the colors of the start and end trim handle depending on object state
809 void
810 TimeAxisViewItem::set_trim_handle_colors()
812 if (frame_handle_start) {
813 if (position_locked) {
814 frame_handle_start->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandleLocked.get();
815 frame_handle_end->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandleLocked.get();
816 } else {
817 frame_handle_start->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandle.get();
818 frame_handle_end->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandle.get();
823 double
824 TimeAxisViewItem::get_samples_per_unit()
826 return(samples_per_unit) ;
829 void
830 TimeAxisViewItem::set_samples_per_unit (double spu)
832 samples_per_unit = spu ;
833 set_position (this->get_position(), this);
834 reset_width_dependent_items ((double)get_duration() / samples_per_unit);
837 void
838 TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
840 if (pixel_width < 2.0) {
842 if (show_vestigial) {
843 vestigial_frame->show();
846 if (name_highlight) {
847 name_highlight->hide();
848 if (name_text) {
849 name_text->hide();
853 if (frame) {
854 frame->hide();
857 if (frame_handle_start) {
858 frame_handle_start->hide();
859 frame_handle_end->hide();
862 } else {
863 vestigial_frame->hide();
865 if (name_highlight) {
867 double height = name_highlight->property_y2 ();
869 if (height < NAME_HIGHLIGHT_THRESH) {
870 name_highlight->hide();
871 if (name_text) {
872 name_text->hide();
874 } else {
875 name_highlight->show();
876 if (name_text && !get_item_name().empty()) {
877 name_text->show();
878 reset_name_width (pixel_width);
882 if (visibility & FullWidthNameHighlight) {
883 name_highlight->property_x2() = pixel_width;
884 } else {
885 name_highlight->property_x2() = pixel_width - 1.0;
890 if (frame) {
891 frame->show();
892 frame->property_x2() = pixel_width;
895 if (frame_handle_start) {
896 if (pixel_width < (2*TimeAxisViewItem::GRAB_HANDLE_LENGTH)) {
897 frame_handle_start->hide();
898 frame_handle_end->hide();
899 } else {
900 frame_handle_start->show();
901 frame_handle_end->property_x1() = pixel_width - (TimeAxisViewItem::GRAB_HANDLE_LENGTH);
902 frame_handle_end->property_x2() = pixel_width;
903 frame_handle_end->show();
909 void
910 TimeAxisViewItem::reset_name_width (double pixel_width)
912 if (name_text == 0) {
913 return;
916 int limit = (int) floor (pixel_width - NAME_X_OFFSET);
917 bool shrinking = (last_name_text_width > pixel_width);
918 int actual_width;
919 ustring ustr;
920 ustring::size_type n;
922 if ((last_name_text_width && // we did this once
923 shrinking && // we're getting smaller
924 (name_text_width <= limit) && // fits the new size
925 (name_text_width <= last_name_text_width - NAME_X_OFFSET))) { // fit into the old size too
926 last_name_text_width = pixel_width;
927 return;
930 /* now check the cache of existing truncations */
932 Gtk::Label foo;
933 Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
935 for (n = item_name.length(); n > 0; --n) {
937 map<ustring::size_type,int>::iterator i;
939 if ((i = name_text_size_cache.find (n)) != name_text_size_cache.end()) {
941 /* we know the length of this substring already */
943 if ((actual_width = (*i).second) < limit) {
945 /* it fits, use it */
947 ustr = item_name.substr (0, n);
948 break;
951 } else {
953 /* we don't know the length of this substring already, so compute
954 it and put it into the cache.
957 layout->set_text (item_name.substr (0, n));
959 int width, height;
960 Gtkmm2ext::get_ink_pixel_size (layout, width, height);
962 name_text_size_cache[n] = width;
964 if ((actual_width = width) < limit) {
965 ustr = item_name.substr (0, n);
966 break;
971 if (n == 0) {
972 name_text->property_text() = "";
973 last_name_text_width = pixel_width;
974 return;
977 /* don't use name for event handling if it leaves no room
978 for trimming to work.
981 if (pixel_width - actual_width < (NAME_X_OFFSET * 2.0)) {
982 if (name_connected) {
983 name_connected = false;
985 } else {
986 if (!name_connected) {
987 name_connected = true;
991 name_text->property_text() = ustr;
992 name_text_width = actual_width;
993 name_text->show();
994 last_name_text_width = pixel_width;
999 //---------------------------------------------------------------------------------------//
1000 // Handle time axis removal
1003 * Handles the Removal of this time axis item
1004 * This _needs_ to be called to alert others of the removal properly, ie where the source
1005 * of the removal came from.
1007 * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method
1008 * just now to capture the source of the removal
1010 * @param src the identity of the object that initiated the change
1012 void
1013 TimeAxisViewItem::remove_this_item(void* src)
1016 defer to idle loop, otherwise we'll delete this object
1017 while we're still inside this function ...
1019 Glib::signal_idle().connect(bind (sigc::ptr_fun (&TimeAxisViewItem::idle_remove_this_item), this, src));
1023 * Callback used to remove this time axis item during the gtk idle loop
1024 * This is used to avoid deleting the obejct while inside the remove_this_item
1025 * method
1027 * @param item the TimeAxisViewItem to remove
1028 * @param src the identity of the object that initiated the change
1030 gint
1031 TimeAxisViewItem::idle_remove_this_item(TimeAxisViewItem* item, void* src)
1033 item->ItemRemoved (item->get_item_name(), src) ; /* EMIT_SIGNAL */
1034 delete item;
1035 item = 0;
1036 return false;