[glom] Print Layout: Allow dragging of rules from the rulers.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] Print Layout: Allow dragging of rules from the rulers.
- Date: Wed, 10 Aug 2011 14:51:30 +0000 (UTC)
commit ce598bc442b3808d93a9bf57bbb6cdfcafde9754
Author: Murray Cumming <murrayc murrayc com>
Date: Wed Aug 10 16:50:55 2011 +0200
Print Layout: Allow dragging of rules from the rulers.
* glom/utility_widgets/canvas/canvas_group_grid.[h|cc]:
Added show_temp_rule().
* glom/utility_widgets/canvas/canvas_editable.[h|cc]:
Added show_temp_rule(), calling the one in the grid.
* glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]:
Constructor: Add a special target to the canvas (drag destination).
Handle button-press on the rulers to identify the orientation.
on_canvas_drag_motion(): Handle the new target, showing the temporary
rule line.
on_canvas_drag_data_received(): Handle the new target, adding a real
rule line.
on_canvas_drag_leave(): clean up.
The rule lines are not saved to the document yet.
ChangeLog | 19 +++
.../print_layouts/window_print_layout_edit.cc | 117 ++++++++++++++++++--
.../print_layouts/window_print_layout_edit.h | 9 ++-
glom/utility_widgets/canvas/canvas_editable.cc | 5 +
glom/utility_widgets/canvas/canvas_editable.h | 6 +-
glom/utility_widgets/canvas/canvas_group_grid.cc | 36 ++++++
glom/utility_widgets/canvas/canvas_group_grid.h | 5 +
7 files changed, 184 insertions(+), 13 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 850b103..44354d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2011-08-10 Murray Cumming <murrayc murrayc com>
+
+ Print Layout: Allow dragging of rules from the rulers.
+
+ * glom/utility_widgets/canvas/canvas_group_grid.[h|cc]:
+ Added show_temp_rule().
+ * glom/utility_widgets/canvas/canvas_editable.[h|cc]:
+ Added show_temp_rule(), calling the one in the grid.
+ * glom/mode_design/print_layouts/window_print_layout_edit.[h|cc]:
+ Constructor: Add a special target to the canvas (drag destination).
+ Handle button-press on the rulers to identify the orientation.
+ on_canvas_drag_motion(): Handle the new target, showing the temporary
+ rule line.
+ on_canvas_drag_data_received(): Handle the new target, adding a real
+ rule line.
+ on_canvas_drag_leave(): clean up.
+
+ The rule lines are not saved to the document yet.
+
2011-08-09 Murray Cumming <murrayc murrayc com>
Print Layout: Actually show rules, if there are some.
diff --git a/glom/mode_design/print_layouts/window_print_layout_edit.cc b/glom/mode_design/print_layouts/window_print_layout_edit.cc
index 2b50891..c4fd3cd 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.cc
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.cc
@@ -37,6 +37,8 @@ namespace Glom
const char* Window_PrintLayout_Edit::glade_id("window_print_layout_edit");
const bool Window_PrintLayout_Edit::glade_developer(true);
+static const char DRAG_TARGET_NAME_RULE[] = "application/x-glom-printoutlayout-rule";
+
Window_PrintLayout_Edit::Window_PrintLayout_Edit(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::Window(cobject),
m_entry_name(0),
@@ -51,6 +53,8 @@ Window_PrintLayout_Edit::Window_PrintLayout_Edit(BaseObjectType* cobject, const
m_spinbutton_height(0),
m_ignore_spinbutton_signals(false),
m_drag_preview_requested(false),
+ m_dragging_temp_rule(false),
+ m_temp_rule_horizontal(false),
m_vruler(0),
m_hruler(0),
m_context_menu(0)
@@ -87,12 +91,26 @@ Window_PrintLayout_Edit::Window_PrintLayout_Edit(BaseObjectType* cobject, const
m_spinbutton_height->signal_value_changed().connect(
sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_spinbutton_height));
+ const Gtk::TargetEntry target_rule(DRAG_TARGET_NAME_RULE, Gtk::TARGET_SAME_APP, 0);
+ m_drag_targets_rule.push_back(target_rule);
+
//The rulers are not in the glade file because they use an unusual widget
//that Glade wouldn't usually know about:
m_vruler = GIMP_RULER(gimp_ruler_new(GTK_ORIENTATION_VERTICAL));
gtk_widget_show(GTK_WIDGET(m_vruler));
+ Glib::wrap(GTK_WIDGET(m_vruler))->drag_source_set(m_drag_targets_rule);
m_hruler = GIMP_RULER(gimp_ruler_new(GTK_ORIENTATION_HORIZONTAL));
gtk_widget_show(GTK_WIDGET(m_hruler));
+ Glib::wrap(GTK_WIDGET(m_hruler))->drag_source_set(m_drag_targets_rule);
+
+ //Handle mouse button presses on the rulers, to start rule dragging:
+ gtk_widget_set_events (GTK_WIDGET(m_hruler), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+ gtk_widget_set_events (GTK_WIDGET(m_vruler), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+
+ Glib::wrap(GTK_WIDGET(m_hruler))->signal_button_press_event().connect(
+ sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_hruler_button_press_event), true);
+ Glib::wrap(GTK_WIDGET(m_vruler))->signal_button_press_event().connect(
+ sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_vruler_button_press_event), false);
//Add the ruler widgets to the table at the left and top:
Gtk::Table* table = 0;
@@ -118,11 +136,13 @@ Window_PrintLayout_Edit::Window_PrintLayout_Edit(BaseObjectType* cobject, const
m_canvas.show();
//Make the canvas a drag-and-drop destination:
+ //TODO: Does this need to be a member variable?
+ m_drag_targets_all = m_drag_targets_rule;
const Gtk::TargetEntry toolbar_target = Gtk::ToolPalette::get_drag_target_item();
- m_drag_targets.push_back(toolbar_target);
+ m_drag_targets_all.push_back(toolbar_target);
//Note that we don't use Gtk::DEST_DEFAULT_DEFAULTS because that would prevent our signal handlers from being used:
- m_canvas.drag_dest_set(m_drag_targets, Gtk::DEST_DEFAULT_HIGHLIGHT, Gdk::ACTION_COPY);
+ m_canvas.drag_dest_set(m_drag_targets_all, Gtk::DEST_DEFAULT_HIGHLIGHT, Gdk::ACTION_COPY);
m_canvas.signal_drag_drop().connect(
sigc::mem_fun(*this, &Window_PrintLayout_Edit::on_canvas_drag_drop) );
m_canvas.signal_drag_motion().connect(
@@ -319,6 +339,28 @@ bool Window_PrintLayout_Edit::on_canvas_drag_motion(const Glib::RefPtr<Gdk::Drag
m_canvas.drag_highlight();
+ double item_x = x;
+ double item_y = y;
+ canvas_convert_from_drag_pixels(item_x, item_y);
+
+ //Show the position in the rulers:
+ gimp_ruler_set_position(m_hruler, item_x);
+ gimp_ruler_set_position(m_vruler, item_y);
+
+ //Handle dragging of the rule from the GimpRuler widget:
+ if(target == DRAG_TARGET_NAME_RULE)
+ {
+ if(m_temp_rule_horizontal)
+ m_canvas.show_temp_rule(0, item_y);
+ else
+ m_canvas.show_temp_rule(item_x, 0);
+
+ drag_context->drag_status(Gdk::ACTION_MOVE, timestamp);
+ return true; //Allow the drop.
+ }
+
+ //Else handle dragging of an item from the ToolPalette:
+
//Create the temporary canvas item if necesary:
if(!m_layout_item_dropping)
{
@@ -333,9 +375,6 @@ bool Window_PrintLayout_Edit::on_canvas_drag_motion(const Glib::RefPtr<Gdk::Drag
drag_context->drag_status(Gdk::ACTION_COPY, timestamp);
//Move the temporary canvas item to the new position:
- double item_x = x;
- double item_y = y;
- canvas_convert_from_drag_pixels(item_x, item_y);
m_layout_item_dropping->snap_position(item_x, item_y);
m_layout_item_dropping->set_xy(item_x, item_y);
@@ -411,10 +450,39 @@ void Window_PrintLayout_Edit::on_canvas_drag_data_received(const Glib::RefPtr<Gd
{
//This is called when an item is dropped on the canvas,
//or after our drag_motion handler has called drag_get_data()):
+
+ const Glib::ustring target = m_canvas.drag_dest_find_target(drag_context);
+ if(target.empty())
+ return;
+
+ double item_x = x;
+ double item_y = y;
+ canvas_convert_from_drag_pixels(item_x, item_y);
+
+ //Handle dragging of the rule from the GimpRuler widget:
+ if(target == DRAG_TARGET_NAME_RULE)
+ {
+ m_canvas.show_temp_rule(0, 0, false);
+
+ if(m_temp_rule_horizontal)
+ m_canvas.add_horizontal_rule(item_y);
+ else
+ m_canvas.add_vertical_rule(item_x);
+
+ drag_context->drag_finish(true, false, timestamp);
+
+ m_dragging_temp_rule = false;
+ return;
+ }
//Discover what toolbar item was dropped:
const PrintLayoutToolbarButton::enumItems item_type = PrintLayoutToolbarButton::get_item_type_from_selection_data(drag_context, selection_data);
-
+ if(item_type == PrintLayoutToolbarButton::ITEM_INVALID)
+ {
+ std::cerr << G_STRFUNC << ": item_type was invalid" << std::endl;
+ return;
+ }
+
if(m_drag_preview_requested)
{
//Create the temporary drag item if necessary:
@@ -428,9 +496,6 @@ void Window_PrintLayout_Edit::on_canvas_drag_data_received(const Glib::RefPtr<Gd
m_layout_item_dropping = CanvasLayoutItem::create(layout_item);
m_canvas.add_canvas_layout_item(m_layout_item_dropping);
- double item_x = x;
- double item_y = y;
- canvas_convert_from_drag_pixels(item_x, item_y);
m_layout_item_dropping->snap_position(item_x, item_y);
m_layout_item_dropping->set_xy(item_x, item_y);
}
@@ -447,6 +512,12 @@ void Window_PrintLayout_Edit::on_canvas_drag_data_received(const Glib::RefPtr<Gd
//Add the item to the canvas:
sharedptr<LayoutItem> layout_item = create_empty_item(item_type);
+ if(!layout_item)
+ {
+ std::cerr << G_STRFUNC << ": layout_item is null." << std::endl;
+ return;
+ }
+
Glib::RefPtr<CanvasLayoutItem> item = CanvasLayoutItem::create(layout_item);
m_canvas.add_canvas_layout_item(item);
double item_x = x;
@@ -463,17 +534,20 @@ void Window_PrintLayout_Edit::on_canvas_drag_data_received(const Glib::RefPtr<Gd
}
}
-
void Window_PrintLayout_Edit::on_canvas_drag_leave(const Glib::RefPtr<Gdk::DragContext>& /* drag_context */, guint /* timestamp */)
{
//Remove the temporary drag item if the cursor was dragged out of the drop widget:
+ //This also seems to be called after a drop, just before getting the data,
+ //therefore we should not do anything here that would stop the drop from succeeding.
if(m_layout_item_dropping)
{
m_layout_item_dropping->remove();
m_layout_item_dropping.reset();
}
-}
+ m_canvas.show_temp_rule(0, 0, false); //Remove it.
+ m_dragging_temp_rule = false;
+}
Window_PrintLayout_Edit::~Window_PrintLayout_Edit()
{
@@ -1233,6 +1307,27 @@ void Window_PrintLayout_Edit::on_spinbutton_height()
m_spinbutton_height->get_value());
}
+bool Window_PrintLayout_Edit::on_hruler_button_press_event(GdkEventButton* event)
+{
+ if(event->button != 1)
+ return true;
+
+ m_dragging_temp_rule = true;
+ m_temp_rule_horizontal = true;
+
+ return false;
+}
+
+bool Window_PrintLayout_Edit::on_vruler_button_press_event(GdkEventButton* event)
+{
+ if(event->button != 1)
+ return true;
+
+ m_dragging_temp_rule = true;
+ m_temp_rule_horizontal = false; //vertical.
+
+ return false;
+}
} //namespace Glom
diff --git a/glom/mode_design/print_layouts/window_print_layout_edit.h b/glom/mode_design/print_layouts/window_print_layout_edit.h
index 395b2b6..01c8a37 100644
--- a/glom/mode_design/print_layouts/window_print_layout_edit.h
+++ b/glom/mode_design/print_layouts/window_print_layout_edit.h
@@ -105,6 +105,9 @@ private:
void on_spinbutton_width();
void on_spinbutton_height();
+ bool on_hruler_button_press_event(GdkEventButton* event);
+ bool on_vruler_button_press_event(GdkEventButton* event);
+
//override:
virtual bool on_configure_event(GdkEventConfigure* event);
@@ -149,6 +152,9 @@ private:
bool m_drag_preview_requested;
Glib::RefPtr<CanvasLayoutItem> m_layout_item_dropping;
+ bool m_dragging_temp_rule;
+ bool m_temp_rule_horizontal; //Otherwise vertical.
+
//A cache of the selected item,
//to avoid repeatedly requesting it:
typedef std::vector< Glib::RefPtr<CanvasLayoutItem> > type_vec_canvas_items;
@@ -161,6 +167,7 @@ private:
typedef LayoutGroup::type_list_items type_list_items;
type_list_items m_layout_items_to_paste;
+ std::vector<Gtk::TargetEntry> m_drag_targets_rule;
GimpRuler* m_vruler;
GimpRuler* m_hruler;
@@ -176,7 +183,7 @@ private:
//Toolbar:
Gtk::HandleBox* m_palette_handle_box; //TODO: The toolbar is already a HandleBox.
- std::vector<Gtk::TargetEntry> m_drag_targets;
+ std::vector<Gtk::TargetEntry> m_drag_targets_all;
PrintLayoutToolbar m_toolbar;
//Context menu for clicking on empty space on the canvas:
diff --git a/glom/utility_widgets/canvas/canvas_editable.cc b/glom/utility_widgets/canvas/canvas_editable.cc
index 0a6d0b4..150ee4e 100644
--- a/glom/utility_widgets/canvas/canvas_editable.cc
+++ b/glom/utility_widgets/canvas/canvas_editable.cc
@@ -162,6 +162,11 @@ void CanvasEditable::add_horizontal_rule(double y)
m_grid->add_horizontal_rule(y);
}
+void CanvasEditable::show_temp_rule(double x, double y, bool show)
+{
+ m_grid->show_temp_rule(x, y, show);
+}
+
void CanvasEditable::set_grid_gap(double gap)
{
m_grid->set_grid_gap(gap);
diff --git a/glom/utility_widgets/canvas/canvas_editable.h b/glom/utility_widgets/canvas/canvas_editable.h
index 907fc36..a2a7cce 100644
--- a/glom/utility_widgets/canvas/canvas_editable.h
+++ b/glom/utility_widgets/canvas/canvas_editable.h
@@ -57,7 +57,11 @@ public:
void set_rules_visibility(bool visible = true);
void add_vertical_rule(double x);
- void add_horizontal_rule(double x);
+ void add_horizontal_rule(double y);
+
+ /** Either @a x or @a y should be 0.
+ */
+ void show_temp_rule(double x, double y, bool show = true);
/** For items not added directly via add_item(),
* but which need to snap to the grid.
diff --git a/glom/utility_widgets/canvas/canvas_group_grid.cc b/glom/utility_widgets/canvas/canvas_group_grid.cc
index fd07e22..13428fe 100644
--- a/glom/utility_widgets/canvas/canvas_group_grid.cc
+++ b/glom/utility_widgets/canvas/canvas_group_grid.cc
@@ -35,6 +35,11 @@ CanvasGroupGrid::CanvasGroupGrid()
{
m_grid_rules_group = Goocanvas::Group::create();
add_child(m_grid_rules_group);
+
+ //Create the temp rule and hide it by default:
+ m_temp_rule = create_rule_line(10, 10, 100, 100);
+ m_temp_rule->property_visibility() = Goocanvas::ITEM_INVISIBLE;
+ add_child(m_temp_rule);
}
CanvasGroupGrid::~CanvasGroupGrid()
@@ -286,5 +291,36 @@ void CanvasGroupGrid::set_rules_visibility(bool visible)
m_grid_lines->lower(m_grid_rules_group);
}
+void CanvasGroupGrid::show_temp_rule(double x, double y, bool show)
+{
+ m_temp_rule->property_visibility() = (show ? Goocanvas::ITEM_VISIBLE : Goocanvas::ITEM_INVISIBLE);
+
+ double left = 0.0;
+ double top = 0.0;
+ double right = 0.0;
+ double bottom = 0.0;
+ Goocanvas::Canvas* canvas = get_canvas();
+ if(canvas)
+ canvas->get_bounds(left, top, right, bottom);
+
+ const bool horizontal = (y == 0);
+
+ if(horizontal)
+ {
+ double points_coordinates[] = {x, top, x , bottom};
+ Goocanvas::Points points(2, points_coordinates);
+ m_temp_rule->property_points() = points;
+ }
+ else
+ {
+ double points_coordinates[] = {left, y, right , y};
+ Goocanvas::Points points(2, points_coordinates);
+ m_temp_rule->property_points() = points;
+ }
+
+ m_temp_rule->raise();
+}
+
+
} //namespace Glom
diff --git a/glom/utility_widgets/canvas/canvas_group_grid.h b/glom/utility_widgets/canvas/canvas_group_grid.h
index 8c814d7..28f2bc1 100644
--- a/glom/utility_widgets/canvas/canvas_group_grid.h
+++ b/glom/utility_widgets/canvas/canvas_group_grid.h
@@ -72,6 +72,10 @@ public:
void set_rules_visibility(bool visible = true);
+ /** Either @a x or @a y should be 0.
+ */
+ void show_temp_rule(double x, double y, bool show = true);
+
private:
void create_grid_lines();
void create_rules();
@@ -86,6 +90,7 @@ private:
Glib::RefPtr<Goocanvas::Grid> m_grid_lines;
Glib::RefPtr<Goocanvas::Group> m_grid_rules_group;
+ Glib::RefPtr<Goocanvas::Polyline> m_temp_rule;
};
} //namespace Glom
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]