diff options
author | Taybin Rutkin <taybin@taybin.com> | 2005-09-25 18:42:24 +0000 |
---|---|---|
committer | Taybin Rutkin <taybin@taybin.com> | 2005-09-25 18:42:24 +0000 |
commit | 209d967b1bb80a9735d690d8f4f0455ecb9970ca (patch) | |
tree | 9d76ddcd7c1ac9d91bb2b1a33d31b66ce4ded5de /gtk2_ardour/imageframe_view.cc | |
parent | e4b9aed743fc765219ac775905a221c017c88fba (diff) |
Initial import of gtk2_ardour.
git-svn-id: svn://localhost/trunk/ardour2@24 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour/imageframe_view.cc')
-rw-r--r-- | gtk2_ardour/imageframe_view.cc | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/gtk2_ardour/imageframe_view.cc b/gtk2_ardour/imageframe_view.cc new file mode 100644 index 0000000000..27fe741204 --- /dev/null +++ b/gtk2_ardour/imageframe_view.cc @@ -0,0 +1,395 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include <algorithm> +#include <cmath> + +#include <gtk--.h> +#include <gtkmmext/gtk_ui.h> + +#include "imageframe_time_axis.h" +#include "imageframe_time_axis_group.h" +#include "marker_time_axis.h" +#include "marker_time_axis_view.h" +#include "canvas-simplerect.h" +#include "public_editor.h" +#include "utils.h" +#include "imageframe_view.h" +#include "canvas-imageframe.h" +#include "gui_thread.h" + +using namespace SigC ; +using namespace ARDOUR ; + +SigC::Signal1<void,ImageFrameView*> ImageFrameView::GoingAway; + +/** + * Constructs a new ImageFrameView upon the canvas + * + * @param item_id unique id of this item + * @param parent the parent canvas item + * @param tv the time axis view that this item is to be placed upon + * @param group the ImageFrameGroup that this item is a member of + * @param spu the current samples per canvas unit + * @param start the start frame ogf this item + * @param duration the duration of this item + * @param rgb_data the rgb data of the image + * @param width the width of the original rgb_data image data + * @param height the width of the origianl rgb_data image data + * @param num_channels the number of color channels within rgb_data + */ +ImageFrameView::ImageFrameView(std::string item_id, + GtkCanvasGroup *parent, + ImageFrameTimeAxis* tv, + ImageFrameTimeAxisGroup* item_group, + double spu, + GdkColor& basic_color, + jack_nframes_t start, + jack_nframes_t duration, + unsigned char* rgb_data, + uint32_t width, + uint32_t height, + uint32_t num_channels) + : TimeAxisViewItem(item_id, parent, *tv, spu, basic_color, start, duration, + TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText| + TimeAxisViewItem::ShowNameHighlight| + TimeAxisViewItem::ShowFrame| + TimeAxisViewItem::ShowHandles)) + +{ + the_parent_group = item_group ; + set_name_text(item_id) ; + + image_data_width = width ; + image_data_height = height ; + image_data_num_channels = num_channels ; + + //This should be art_free'd once the ArtPixBuf is destroyed - this should happen when we destroy the imageframe canvas item + unsigned char* the_rgb_data = (unsigned char*) art_alloc(width*height*num_channels) ; + memcpy(the_rgb_data, rgb_data, (width*height*num_channels)) ; + + ArtPixBuf* pbuf ; + pbuf = art_pixbuf_new_rgba(the_rgb_data, width, height, (num_channels * width)); + imageframe = 0 ; + + //calculate our image width based on the track height + double im_ratio = (double)width/(double)height ; + int im_width = (int)((double)(trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) * im_ratio) ; + + imageframe = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_imageframe_get_type(), + "pixbuf", pbuf, + "x", (gdouble) 1.0, + "y", (gdouble) 1.0, + "anchor", GTK_ANCHOR_NW, + "width", (gdouble) im_width, + "height", (gdouble) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE), + NULL) ; + + + gtk_signal_connect (GTK_OBJECT(frame_handle_start), "event", + (GtkSignalFunc) PublicEditor::canvas_imageframe_start_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(frame_handle_end), "event", + (GtkSignalFunc) PublicEditor::canvas_imageframe_end_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(group), "event", + (GtkSignalFunc) PublicEditor::canvas_imageframe_item_view_event, this); + + /* handle any specific details required by the initial start end duration values */ + + gtk_canvas_item_raise_to_top(frame_handle_start) ; + gtk_canvas_item_raise_to_top(frame_handle_end) ; + + set_position(start, this) ; + set_duration(duration, this) ; +} + +/** + * Destructor + * Reposible for removing and destroying all marker items associated with this item + */ +ImageFrameView::~ImageFrameView() +{ + GoingAway (this); + + // destroy any marker items we have associated with this item + + for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter) + { + MarkerView* mv = (*iter) ; + + MarkerViewList::iterator next = iter ; + next++ ; + + // remove the item from our marker list + // the current iterator becomes invalid after this point, so we cannot call next upon it + // luckily enough, we already have next + marker_view_list.erase(iter) ; + + // remove the item from the marker time axis + MarkerTimeAxisView* mtav = dynamic_cast<MarkerTimeAxis*>(&mv->get_time_axis_view())->get_view() ; + if(mtav) + { + mtav->remove_marker_view(mv, this) ; + } + + mv->set_marked_item(0) ; + delete mv ; + mv = 0 ; + + // set our iterator to next, as we have invalided the current iterator with the call to erase + iter = next ; + } + + // if we are the currently selected item withi the parent track, we need to se-select + if(the_parent_group) + { + if(the_parent_group->get_view().get_selected_imageframe_view() == this) + { + the_parent_group->get_view().clear_selected_imageframe_item(false) ; + } + } + + if(imageframe) + { + gtk_object_destroy(GTK_OBJECT(imageframe)) ; + imageframe = 0 ; + } +} + + +//---------------------------------------------------------------------------------------// +// Position and duration Accessors/Mutators + +/** + * Set the position of this item to the specified value + * + * @param pos the new position + * @param src the identity of the object that initiated the change + * @return true if the position change was a success, false otherwise + */ +bool +ImageFrameView::set_position(jack_nframes_t pos, void* src) +{ + jack_nframes_t old_pos = frame_position ; + + // do the standard stuff + bool ret = TimeAxisViewItem::set_position(pos, src) ; + + // everything went ok with the standard stuff? + if(ret) + { + /* move each of our associated markers with this ImageFrameView */ + for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) + { + // calculate the offset of the marker + MarkerView* mv = (MarkerView*)*i ; + jack_nframes_t marker_old_pos = mv->get_position() ; + + mv->set_position(pos + (marker_old_pos - old_pos), src) ; + } + } + + return(ret) ; +} + +/** + * Sets the duration of this item + * + * @param dur the new duration of this item + * @param src the identity of the object that initiated the change + * @return true if the duration change was succesful, false otherwise + */ +bool +ImageFrameView::set_duration(jack_nframes_t dur, void* src) +{ + /* do the standard stuff */ + bool ret = TimeAxisViewItem::set_duration(dur, src) ; + + // eveything went ok with the standard stuff? + if(ret) + { + /* handle setting the sizes of our canvas itesm based on the new duration */ + gtk_canvas_item_set(imageframe, "drawwidth", (gdouble) trackview.editor.frame_to_pixel(get_duration()), NULL) ; + } + + return(ret) ; +} + +//---------------------------------------------------------------------------------------// +// Parent Component Methods + +/** + * Sets the parent ImageFrameTimeAxisGroup of thie item + * each Item must be part of exactly one group (or 'scene') upon the timeline + * + * @param group the new parent group + */ +void +ImageFrameView::set_time_axis_group(ImageFrameTimeAxisGroup* group) +{ + the_parent_group = group ; +} + +/** + * Returns the parent group of this item + * + * @return the parent group of this item + */ +ImageFrameTimeAxisGroup* +ImageFrameView::get_time_axis_group() +{ + return(the_parent_group) ; +} + + +//---------------------------------------------------------------------------------------// +// ui methods + +/** + * Set the height of this item + * + * @param h the new height + */ +void +ImageFrameView::set_height (gdouble h) +{ + // set the image size + // @todo might have to re-get the image data, for a large height...hmmm. + double im_ratio = (double)image_data_width/(double)image_data_height ; + int im_width = (int)((double)(h - TimeAxisViewItem::NAME_Y_OFFSET) * im_ratio) ; + gtk_canvas_item_set(imageframe, "width", (gdouble)im_width, NULL) ; + gtk_canvas_item_set(imageframe, "height",(gdouble) (h - TimeAxisViewItem::NAME_Y_OFFSET), NULL) ; + + + gtk_canvas_item_raise_to_top(frame) ; + gtk_canvas_item_raise_to_top(imageframe) ; + gtk_canvas_item_raise_to_top(name_highlight) ; + gtk_canvas_item_raise_to_top(name_text) ; + gtk_canvas_item_raise_to_top(frame_handle_start) ; + gtk_canvas_item_raise_to_top(frame_handle_end) ; + + gtk_canvas_item_set (name_text, "y", h - TimeAxisViewItem::NAME_Y_OFFSET, NULL); + gtk_canvas_item_set (frame, "y2", h, NULL); + + gtk_canvas_item_set (name_highlight, "y1", (gdouble) h - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE, "y2", (gdouble) h - 1.0, NULL); +} + + +//---------------------------------------------------------------------------------------// +// MarkerView methods + +/** + * Adds a markerView to the list of marker views associated with this item + * + * @param item the marker item to add + * @param src the identity of the object that initiated the change + */ +void +ImageFrameView::add_marker_view_item(MarkerView* item, void* src) +{ + marker_view_list.push_back(item) ; + + item->GoingAway.connect(bind(slot(*this, &ImageFrameView::remove_marker_view_item), (void*)this)); + + MarkerViewAdded(item, src) ; /* EMIT_SIGNAL */ +} + +/** + * Removes the named marker view from the list of marker view associated with this item + * The Marker view is not destroyed on removal, so the caller must handle the item themself + * + * @param markId the id/name of the item to remove + * @param src the identity of the object that initiated the change + * @return the removed marker item + */ +MarkerView* +ImageFrameView::remove_named_marker_view_item(std::string markerId, void* src) +{ + MarkerView* mv = 0 ; + MarkerViewList::iterator i = marker_view_list.begin() ; + + while(i != marker_view_list.end()) + { + if (((MarkerView*)*i)->get_item_name() == markerId) + { + mv = (*i) ; + + marker_view_list.erase(i) ; + + MarkerViewRemoved(mv,src) ; /* EMIT_SIGNAL */ + + // iterator is now invalid, but since we should only ever have + // one item with the specified name, things are ok, and we can + // break from the while loop + break ; + } + i++ ; + } + + return(mv) ; +} + +/** + * Removes item from the list of marker views assocaited with this item + * This method will do nothing if item if not assiciated with this item + * + * @param item the item to remove + * @param src the identity of the object that initiated the change + */ +void +ImageFrameView::remove_marker_view_item(MarkerView* mv, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameView::remove_marker_view_item), mv, src)); + + MarkerViewList::iterator i ; + + if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) { + marker_view_list.erase(i) ; + MarkerViewRemoved (mv, src) ; /* EMIT_SIGNAL */ + } +} + +/** + * Determines if the named marker is one of those associated with this item + * + * @param markId the id/name of the item to search for + */ +bool +ImageFrameView::has_marker_view_item(std::string mname) +{ + bool result = false ; + + for (MarkerViewList::iterator ci = marker_view_list.begin(); ci != marker_view_list.end(); ++ci) + { + if (((MarkerView*)*ci)->get_item_name() == mname) + { + result = true ; + + // found the item, so we can break the for loop + break ; + } + } + + return(result) ; +} |