Tidied and simplified video display widget, and added cursor support to

the ibeam and arrow tool
This commit is contained in:
Joel Holdsworth 2008-08-04 16:39:36 +01:00
parent fdab62a5d8
commit 2ee6f6be62
15 changed files with 217 additions and 219 deletions

View file

@ -38,7 +38,8 @@ TimelinePanel::TimelinePanel() :
arrowTool(Gtk::StockID("arrow")),
iBeamTool(Gtk::StockID("i_beam")),
zoomIn(Stock::ZOOM_IN),
zoomOut(Stock::ZOOM_OUT)
zoomOut(Stock::ZOOM_OUT),
updatingToolbar(false)
{
// Setup the toolbar
toolbar.append(arrowTool, mem_fun(this,
@ -63,6 +64,7 @@ TimelinePanel::TimelinePanel() :
void
TimelinePanel::on_arrow_tool()
{
if(updatingToolbar) return;
timelineWidget.set_tool(timeline::Arrow);
update_tool_buttons();
}
@ -70,6 +72,7 @@ TimelinePanel::on_arrow_tool()
void
TimelinePanel::on_ibeam_tool()
{
if(updatingToolbar) return;
timelineWidget.set_tool(timeline::IBeam);
update_tool_buttons();
}
@ -77,6 +80,7 @@ TimelinePanel::on_ibeam_tool()
void
TimelinePanel::on_zoom_in()
{
timelineWidget.zoom_view(ZoomToolSteps);
update_zoom_buttons();
}
@ -90,17 +94,14 @@ TimelinePanel::on_zoom_out()
void
TimelinePanel::update_tool_buttons()
{
// This is included to prevent recursion
static bool updating = false;
if(!updating)
{
if(!updatingToolbar)
{
updating = true;
updatingToolbar = true;
const timeline::ToolType tool = timelineWidget.get_tool();
arrowTool.set_active(tool == timeline::Arrow);
iBeamTool.set_active(tool == timeline::IBeam);
updating = false;
updatingToolbar = false;
}
}

View file

@ -69,6 +69,9 @@ private:
Gtk::ToolButton zoomIn;
Gtk::ToolButton zoomOut;
// Internals
bool updatingToolbar;
//----- Constants -----//
static const int ZoomToolSteps;
};

View file

@ -177,25 +177,28 @@ TimelineWidget::set_tool(ToolType tool_type)
{
// Tidy up old tool
if(tool != NULL)
{
// Do we need to change tools?
if(tool->get_type() == tool_type)
return;
delete tool;
}
{
// Do we need to change tools?
//if(tool->get_type() == tool_type)
// return;
delete tool;
}
// Create the new tool
switch(tool_type)
{
case timeline::Arrow:
tool = new timeline::ArrowTool();
tool = new timeline::ArrowTool(this);
break;
case timeline::IBeam:
tool = new timeline::IBeamTool();
tool = new timeline::IBeamTool(this);
break;
}
// Apply the cursor if possible
tool->apply_cursor();
}
void

View file

@ -148,6 +148,7 @@ protected:
friend class timeline::TimelineBody;
friend class timeline::HeaderContainer;
friend class timeline::Tool;
};
} // namespace widgets

View file

@ -39,7 +39,9 @@ HeaderContainer::HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline
{
REQUIRE(timeline_widget != NULL);
set_flags(Gtk::NO_WINDOW); // This widget will not have a window at first
// This widget will not have a window at first
set_flags(Gtk::NO_WINDOW);
set_redraw_on_allocate(false);
// Connect to the timeline widget's vertical scroll event,

View file

@ -46,80 +46,80 @@ class Track;
* associated with timeline tracks.
*/
class HeaderContainer : public Gtk::Container
{
public:
/**
* Constructor
*
* @param[in] timeline_widget A pointer to the owner timeline widget
*/
HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline_widget);
/**
* Attaches the header all the header widgets of root
* tracks to this control.
*
* @note This must be called when the track list changes
* to synchronise the headers with the timeline body and
* the backend.
*/
void update_headers();
/* ===== Overrides ===== */
private:
void on_realize();
void on_unrealize();
{
public:
/**
* Constructor
*
* @param[in] timeline_widget A pointer to the owner timeline widget
*/
HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline_widget);
void on_size_allocate (Gtk::Allocation& allocation);
void on_size_request (Gtk::Requisition* requisition);
void forall_vfunc(gboolean include_internals, GtkCallback callback,
gpointer callback_data);
/* ===== Events ===== */
private:
void on_scroll();
/**
* Attaches the header all the header widgets of root
* tracks to this control.
*
* @note This must be called when the track list changes
* to synchronise the headers with the timeline body and
* the backend.
*/
void update_headers();
/* ===== Overrides ===== */
private:
void on_realize();
void on_unrealize();
void on_size_allocate (Gtk::Allocation& allocation);
void on_size_request (Gtk::Requisition* requisition);
/* ===== Internals ===== */
private:
void forall_vfunc(gboolean include_internals, GtkCallback callback,
gpointer callback_data);
/**
* Moves all the header widgets to the correct position
* given scroll, stacking etc.
*/
void layout_headers();
/* ===== Events ===== */
private:
void on_scroll();
private:
/* ===== Internals ===== */
private:
/**
* Moves all the header widgets to the correct position
* given scroll, stacking etc.
*/
void layout_headers();
/**
* The owner TimelineWidget of which this class is a helper
*/
lumiera::gui::widgets::TimelineWidget *timelineWidget;
private:
/**
* A structure to represent a header widget and it's
* associated track
*/
struct RootHeader
{
Glib::RefPtr<Gtk::Widget> widget;
Track *track;
};
/**
* Contains a list of the root currently present on
* the timeline view
*/
std::vector< RootHeader > rootHeaders;
/**
* The owner TimelineWidget of which this class is a helper
*/
lumiera::gui::widgets::TimelineWidget *timelineWidget;
/**
* The widget's window object.
*
* @note This is needed for the sake of clipping when
* widgets are scrolled.
*/
Glib::RefPtr<Gdk::Window> gdkWindow;
/**
* A structure to represent a header widget and it's
* associated track
*/
struct RootHeader
{
Glib::RefPtr<Gtk::Widget> widget;
Track *track;
};
/**
* Contains a list of the root currently present on
* the timeline view
*/
std::vector< RootHeader > rootHeaders;
/**
* The widget's window object.
*
* @note This is needed for the sake of clipping when
* widgets are scrolled.
*/
Glib::RefPtr<Gdk::Window> gdkWindow;
};
} // namespace timeline
} // namespace widgets

View file

@ -27,7 +27,8 @@ namespace gui {
namespace widgets {
namespace timeline {
ArrowTool::ArrowTool()
ArrowTool::ArrowTool(TimelineWidget *timeline_widget) :
Tool(timeline_widget)
{
}
@ -38,6 +39,12 @@ ArrowTool::get_type() const
return Arrow;
}
Gdk::Cursor
ArrowTool::get_cursor() const
{
return Gdk::Cursor(Gdk::ARROW);
}
} // namespace timeline
} // namespace widgets
} // namespace gui

View file

@ -37,9 +37,12 @@ namespace timeline {
class ArrowTool : public Tool
{
public:
ArrowTool();
ArrowTool(TimelineWidget *timeline_widget);
ToolType get_type() const;
protected:
Gdk::Cursor get_cursor() const;
};
} // namespace timeline

View file

@ -61,7 +61,6 @@ TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget *timeline_widge
"Track Background",
"The background colour of timeline tracks",
GDK_TYPE_COLOR, G_PARAM_READABLE));
}
void
@ -69,12 +68,15 @@ TimelineBody::on_realize()
{
Widget::on_realize();
// We wish to receive all event notifications
// We wish to receive event notifications
add_events(
Gdk::POINTER_MOTION_MASK |
Gdk::SCROLL_MASK |
Gdk::BUTTON_PRESS_MASK |
Gdk::BUTTON_RELEASE_MASK);
// Apply the cursor if possible
timelineWidget->tool->apply_cursor();
}
void

View file

@ -27,9 +27,9 @@ namespace gui {
namespace widgets {
namespace timeline {
IBeamTool::IBeamTool()
IBeamTool::IBeamTool(TimelineWidget *timeline_widget) :
Tool(timeline_widget)
{
}
ToolType
@ -38,6 +38,12 @@ IBeamTool::get_type() const
return IBeam;
}
Gdk::Cursor
IBeamTool::get_cursor() const
{
return Gdk::Cursor(Gdk::XTERM);
}
} // namespace timeline
} // namespace widgets
} // namespace gui

View file

@ -38,9 +38,12 @@ namespace timeline {
class IBeamTool : public Tool
{
public:
IBeamTool();
IBeamTool(TimelineWidget *timeline_widget);
ToolType get_type() const;
protected:
Gdk::Cursor get_cursor() const;
};
} // namespace timeline

View file

@ -21,15 +21,36 @@
* *****************************************************/
#include "timeline-tool.hpp"
#include "../timeline-widget.hpp"
namespace lumiera {
namespace gui {
namespace widgets {
namespace timeline {
Tool::Tool()
Tool::Tool(TimelineWidget *timeline_widget) :
timelineWidget(timeline_widget)
{
REQUIRE(timeline_widget != NULL);
REQUIRE(timeline_widget->body != NULL);
}
bool
Tool::apply_cursor()
{
REQUIRE(timelineWidget != NULL);
if(timelineWidget->body == NULL)
return false;
Glib::RefPtr<Gdk::Window> window =
timelineWidget->body->get_window();
if(!window)
return false;
window->set_cursor(get_cursor());
return true;
}
} // namespace timeline

View file

@ -27,11 +27,14 @@
#ifndef TIMELINE_TOOL_HPP
#define TIMELINE_TOOL_HPP
#include <gtkmm.h>
#include "../../gtk-lumiera.hpp"
namespace lumiera {
namespace gui {
namespace widgets {
class TimelineWidget;
namespace timeline {
enum ToolType
@ -43,10 +46,19 @@ enum ToolType
class Tool
{
public:
Tool();
protected:
Tool(TimelineWidget *timeline_widget);
public:
virtual ToolType get_type() const = 0;
bool apply_cursor();
protected:
virtual Gdk::Cursor get_cursor() const = 0;
protected:
TimelineWidget *timelineWidget;
};

View file

@ -36,128 +36,67 @@ namespace gui {
namespace widgets {
VideoDisplayWidget::VideoDisplayWidget() :
gdkWindow(NULL),
displayer(NULL)
{
set_flags(Gtk::NO_WINDOW);
}
{
}
VideoDisplayWidget::~VideoDisplayWidget()
{
if(displayer != NULL)
delete displayer;
}
{
if(displayer != NULL)
delete displayer;
}
void
VideoDisplayWidget::on_realize()
{
set_flags(Gtk::NO_WINDOW);
{
// Call base class:
Gtk::Widget::on_realize();
// Call base class:
Gtk::Widget::on_realize();
// Set colors
modify_bg(Gtk::STATE_NORMAL, Gdk::Color("black"));
// Create the GdkWindow:
GdkWindowAttr attributes;
memset(&attributes, 0, sizeof(attributes));
if(displayer != NULL)
delete displayer;
displayer = createDisplayer(this, 320, 240);
Gtk::Allocation allocation = get_allocation();
// Set initial position and size of the Gdk::Window:
attributes.x = allocation.get_x();
attributes.y = allocation.get_y();
attributes.width = allocation.get_width();
attributes.height = allocation.get_height();
attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.wclass = GDK_INPUT_OUTPUT;
gdkWindow = Gdk::Window::create(get_window() /* parent */, &attributes,
GDK_WA_X | GDK_WA_Y);
unset_flags(Gtk::NO_WINDOW);
set_window(gdkWindow);
// Set colors
modify_bg(Gtk::STATE_NORMAL, Gdk::Color("black"));
// Make the widget receive expose events
gdkWindow->set_user_data(gobj());
if(displayer != NULL)
delete displayer;
displayer = createDisplayer(this, 320, 240);
add_events(Gdk::ALL_EVENTS_MASK);
}
void
VideoDisplayWidget::on_unrealize()
{
gdkWindow.clear();
//Call base class:
Gtk::Widget::on_unrealize();
}
add_events(Gdk::ALL_EVENTS_MASK);
}
bool
VideoDisplayWidget::on_button_press_event (GdkEventButton* event)
{
unsigned char buffer[320 * 240 * 4];
{
unsigned char buffer[320 * 240 * 4];
for(int i = 0; i < 320*240*4; i++)
buffer[i] = rand();
for(int i = 0; i < 320*240*4; i++)
buffer[i] = rand();
displayer->put((void*)buffer);
displayer->put((void*)buffer);
return true;
}
bool
VideoDisplayWidget::on_expose_event(GdkEventExpose* event)
{
// This is where we draw on the window
/*Glib::RefPtr<Gdk::Window> window = get_window();
if(window)
{
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
if(event)
{
// clip to the area that needs to be re-exposed so we don't draw any
// more than we need to.
cr->rectangle(event->area.x, event->area.y,
event->area.width, event->area.height);
cr->clip();
}
// Paint the background
cr->set_source_rgb(0.0, 0.0, 0.0);
cr->paint();
}*/
return true;
}
return true;
}
Displayer*
VideoDisplayWidget::createDisplayer( Gtk::Widget *drawingArea, int width, int height )
{
REQUIRE(drawingArea != NULL);
REQUIRE(width > 0 && height > 0);
Displayer *displayer = NULL;
displayer = new XvDisplayer( drawingArea, width, height );
if ( !displayer->usable() )
{
delete displayer;
displayer = NULL;
}
{
REQUIRE(drawingArea != NULL);
REQUIRE(width > 0 && height > 0);
Displayer *displayer = NULL;
displayer = new XvDisplayer( drawingArea, width, height );
if ( !displayer->usable() )
{
delete displayer;
displayer = NULL;
}
if ( displayer == NULL )
{
displayer = new GdkDisplayer( drawingArea, width, height );
}
if ( displayer == NULL )
{
displayer = new GdkDisplayer( drawingArea, width, height );
}
return displayer;
}
return displayer;
}
} // namespace widgets
} // namespace gui

View file

@ -36,34 +36,29 @@ namespace lumiera {
namespace gui {
namespace widgets {
class VideoDisplayWidget : public Gtk::Widget
{
public:
VideoDisplayWidget();
class VideoDisplayWidget : public Gtk::DrawingArea
{
public:
VideoDisplayWidget();
~VideoDisplayWidget();
~VideoDisplayWidget();
/* ===== Overrides ===== */
private:
virtual void on_realize();
/* ===== Overrides ===== */
private:
virtual void on_realize();
virtual void on_unrealize();
virtual bool on_expose_event(GdkEventExpose* event);
// TEST CODE!!!!
virtual bool on_button_press_event (GdkEventButton* event);
// TEST CODE!!!!
virtual bool on_button_press_event (GdkEventButton* event);
/* ===== Internals ===== */
private:
static Displayer*
createDisplayer( Gtk::Widget *drawingArea, int width, int height );
/* ===== Internals ===== */
private:
static Displayer*
createDisplayer( Gtk::Widget *drawingArea, int width, int height );
private:
private:
Glib::RefPtr<Gdk::Window> gdkWindow;
Displayer *displayer;
};
Displayer *displayer;
};
} // namespace widgets
} // namespace gui