[glom] Update EggSpreadTableDnd from libegg.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] Update EggSpreadTableDnd from libegg.
- Date: Thu, 1 Sep 2011 10:07:29 +0000 (UTC)
commit 4474bc6e0b1e1d64224b50a6fb4724e9b715db69
Author: Murray Cumming <murrayc murrayc com>
Date: Thu Sep 1 12:06:56 2011 +0200
Update EggSpreadTableDnd from libegg.
* glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
Updated from libegg.
* glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
Wrap the new API to add and remove widgets. Note the extra reference() in
remove_child(), like Gtk::Container::remove().
* glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc: Adapt.
* glom/utility_widgets/flowtable.[h|cc]: Adapt and make several corrections,
for instance to really find our intermediate hbox parents.
However, there is still a warning (from our code) about trying to remove a
hbox that has no parent.
* glom/mode_data/flowtablewithfields.[h|cc]: Remove the add_before parameters,
always adding at the end, because we do not need the ability to insert
anywhere else, and doing so required examining the children, but
EggSpreadTableDnd adds internal children that we don't want to care about.
ChangeLog | 19 +
glom/mode_data/flowtablewithfields.cc | 126 ++----
glom/mode_data/flowtablewithfields.h | 16 +-
.../eggspreadtable/eggspreadtablednd.c | 470 +++++++++++---------
.../eggspreadtable/eggspreadtablednd.h | 14 +-
.../eggspreadtablemm/eggspreadtabledndmm.cc | 30 ++
.../eggspreadtablemm/eggspreadtabledndmm.h | 5 +
.../eggspreadtablemm/eggspreadtablemm.h | 3 +-
.../eggspreadtablemm/test_spreadtablednd.cc | 4 +-
glom/utility_widgets/flowtable.cc | 242 +++++------
glom/utility_widgets/flowtable.h | 16 +-
po/ChangeLog | 6 +
po/POTFILES.in | 1 +
13 files changed, 510 insertions(+), 442 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c1f4845..974c593 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2011-09-01 Murray Cumming <murrayc murrayc com>
+
+ Update EggSpreadTableDnd from libegg.
+
+ * glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
+ Updated from libegg.
+ * glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
+ Wrap the new API to add and remove widgets. Note the extra reference() in
+ remove_child(), like Gtk::Container::remove().
+ * glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc: Adapt.
+ * glom/utility_widgets/flowtable.[h|cc]: Adapt and make several corrections,
+ for instance to really find our intermediate hbox parents.
+ However, there is still a warning (from our code) about trying to remove a
+ hbox that has no parent.
+ * glom/mode_data/flowtablewithfields.[h|cc]: Remove the add_before parameters,
+ always adding at the end, because we do not need the ability to insert
+ anywhere else, and doing so required examining the children, but
+ EggSpreadTableDnd adds internal children that we don't want to care about.
+
2011-08-31 Murray Cumming <murrayc murrayc com>
Print Layout: Allow the user to choose row and column line widths and color.
diff --git a/glom/mode_data/flowtablewithfields.cc b/glom/mode_data/flowtablewithfields.cc
index 7c5f430..4fa95bb 100644
--- a/glom/mode_data/flowtablewithfields.cc
+++ b/glom/mode_data/flowtablewithfields.cc
@@ -65,11 +65,15 @@ FlowTableWithFields::~FlowTableWithFields()
{
View_Composite_Glom* pViewFirst = dynamic_cast<View_Composite_Glom*>(iter->m_first);
if(pViewFirst)
+ {
remove_view(pViewFirst);
+ }
- View_Composite_Glom* pViewSecond = dynamic_cast<View_Composite_Glom*>(iter->m_second);
+ View_Composite_Glom* pViewSecond = dynamic_cast<View_Composite_Glom*>(iter->m_second);
if(pViewSecond)
+ {
remove_view(pViewSecond);
+ }
}
}
@@ -90,16 +94,11 @@ void FlowTableWithFields::set_table(const Glib::ustring& table_name)
void FlowTableWithFields::add_layout_item(const sharedptr<LayoutItem>& item)
{
- add_layout_item_at_position(item, m_list_layoutwidgets.end());
-}
-
-void FlowTableWithFields::add_layout_item_at_position(const sharedptr<LayoutItem>& item, const type_list_layoutwidgets::iterator& add_before)
-{
//Get derived type and do the appropriate thing:
sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(item);
if(field)
{
- add_field_at_position(field, m_table_name, add_before);
+ add_field(field, m_table_name);
//Do not allow editing of auto-increment fields:
sharedptr<const Field> field_details = field->get_full_field_details();
@@ -116,41 +115,41 @@ void FlowTableWithFields::add_layout_item_at_position(const sharedptr<LayoutItem
sharedptr<LayoutItem_Portal> portal = sharedptr<LayoutItem_Portal>::cast_dynamic(item);
if(portal)
{
- add_layout_portal_at_position(portal, add_before);
+ add_layout_portal(portal);
}
else
{
sharedptr<LayoutItem_Notebook> notebook = sharedptr<LayoutItem_Notebook>::cast_dynamic(item);
if(notebook)
{
- add_layout_notebook_at_position(notebook, add_before);
+ add_layout_notebook(notebook);
}
else
{
sharedptr<LayoutGroup> group = sharedptr<LayoutGroup>::cast_dynamic(item);
if(group)
- add_layout_group_at_position(group, add_before);
+ add_layout_group(group);
else
{
sharedptr<LayoutItem_Button> layout_button = sharedptr<LayoutItem_Button>::cast_dynamic(item);
if(layout_button)
- add_button_at_position(layout_button, m_table_name, add_before);
+ add_button(layout_button, m_table_name);
else
{
sharedptr<LayoutItem_Text> layout_textobject = sharedptr<LayoutItem_Text>::cast_dynamic(item);
if(layout_textobject)
- add_textobject_at_position(layout_textobject, m_table_name, add_before);
+ add_textobject(layout_textobject, m_table_name);
else
{
sharedptr<LayoutItem_Image> layout_imageobject = sharedptr<LayoutItem_Image>::cast_dynamic(item);
if(layout_imageobject)
- add_imageobject_at_position(layout_imageobject, m_table_name, add_before);
+ add_imageobject(layout_imageobject, m_table_name);
else
{
sharedptr<LayoutItem_Placeholder> layout_placeholder =
sharedptr<LayoutItem_Placeholder>::cast_dynamic(item);
if(layout_placeholder)
- add_placeholder_at_position(layout_placeholder, m_table_name, add_before);
+ add_placeholder(layout_placeholder, m_table_name);
}
}
}
@@ -162,11 +161,6 @@ void FlowTableWithFields::add_layout_item_at_position(const sharedptr<LayoutItem
void FlowTableWithFields::add_layout_group(const sharedptr<LayoutGroup>& group, bool with_indent)
{
- add_layout_group_at_position(group, m_list_layoutwidgets.end(), with_indent);
-}
-
-void FlowTableWithFields::add_layout_group_at_position(const sharedptr<LayoutGroup>& group, const type_list_layoutwidgets::iterator& add_before, bool with_indent)
-{
if(!group)
return;
@@ -234,7 +228,7 @@ void FlowTableWithFields::add_layout_group_at_position(const sharedptr<LayoutGro
m_sub_flow_tables.push_back(flow_table);
flow_table->set_layout_item(group, m_table_name);
- add_layoutwidgetbase(flow_table, add_before);
+ add_layoutwidgetbase(flow_table);
//Connect signal:
flow_table->signal_field_edited().connect( sigc::mem_fun(*this, &FlowTableWithFields::on_flowtable_entry_edited) );
@@ -325,7 +319,7 @@ Box_Data_Calendar_Related* FlowTableWithFields::create_related_calendar(const sh
return 0;
}
-void FlowTableWithFields::add_layout_portal_at_position(const sharedptr<LayoutItem_Portal>& portal, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_layout_portal(const sharedptr<LayoutItem_Portal>& portal)
{
Box_Data_Portal* portal_box = 0;
sharedptr<LayoutItem_CalendarPortal> calendar_portal = sharedptr<LayoutItem_CalendarPortal>::cast_dynamic(portal);
@@ -337,13 +331,13 @@ void FlowTableWithFields::add_layout_portal_at_position(const sharedptr<LayoutIt
if(portal_box)
{
add(*portal_box, true /* expand */);
- add_layoutwidgetbase(portal_box, add_before);
+ add_layoutwidgetbase(portal_box);
}
else
std::cerr << G_STRFUNC << ": No portal was created." << std::endl;
}
-void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<LayoutItem_Notebook>& notebook, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_layout_notebook(const sharedptr<LayoutItem_Notebook>& notebook)
{
if(!notebook)
return;
@@ -379,7 +373,7 @@ void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<Layout
portal_box->show();
notebook_widget->append_page(*portal_box, *tab_label);
- add_layoutwidgetbase(portal_box, add_before);
+ add_layoutwidgetbase(portal_box);
}
else
{
@@ -429,7 +423,7 @@ void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<Layout
m_sub_flow_tables.push_back(flow_table);
flow_table->set_layout_item(group, m_table_name);
- add_layoutwidgetbase(flow_table, add_before);
+ add_layoutwidgetbase(flow_table);
//Connect signal:
flow_table->signal_field_edited().connect( sigc::mem_fun(*this, &FlowTableWithFields::on_flowtable_entry_edited) );
@@ -443,13 +437,9 @@ void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<Layout
}
}
- add_layoutwidgetbase(notebook_widget, add_before);
+ add_layoutwidgetbase(notebook_widget);
//add_view(button); //So it can get the document.
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before (*notebook_widget, *widget, true /* expand */);
- else
- add(*notebook_widget, true /* expand */);
+ add(*notebook_widget, true /* expand */);
}
/*
@@ -507,17 +497,12 @@ void FlowTableWithFields::add_group(const Glib::ustring& group_name, const Glib:
void FlowTableWithFields::add_field(const sharedptr<LayoutItem_Field>& layoutitem_field, const Glib::ustring& table_name)
{
- add_field_at_position(layoutitem_field, table_name, m_list_layoutwidgets.end());
-}
-
-void FlowTableWithFields::add_field_at_position(const sharedptr<LayoutItem_Field>& layoutitem_field, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before)
-{
Info info;
info.m_field = layoutitem_field;
//Add the entry or checkbox (handled by the DataWidget)
DataWidget* pDataWidget = Gtk::manage(new DataWidget(layoutitem_field, table_name, get_document()) ); //TODO_Leak: Possibly leaked, according to valgrind.
- add_layoutwidgetbase(pDataWidget, add_before);
+ add_layoutwidgetbase(pDataWidget);
add_view(pDataWidget); //So it can get the document.
info.m_second = pDataWidget;
@@ -555,11 +540,7 @@ void FlowTableWithFields::add_field_at_position(const sharedptr<LayoutItem_Field
eventbox->set_events(Gdk::ALL_EVENTS_MASK);
eventbox->show_all();
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before(*eventbox, *(info.m_second), *widget, true);
- else
- add(*eventbox, *(info.m_second), true);
+ add(*eventbox, *(info.m_second), true);
info.m_second->signal_edited().connect( sigc::bind(sigc::mem_fun(*this, &FlowTableWithFields::on_entry_edited), layoutitem_field) ); //TODO: Is it a good idea to bind the LayoutItem? sigc::bind() probably stores a copy at this point.
@@ -574,7 +555,7 @@ void FlowTableWithFields::add_field_at_position(const sharedptr<LayoutItem_Field
}
-void FlowTableWithFields::add_button_at_position(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_button(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name)
{
//Add the widget
ButtonGlom* button = Gtk::manage(new ButtonGlom());
@@ -587,7 +568,7 @@ void FlowTableWithFields::add_button_at_position(const sharedptr<LayoutItem_Butt
button->show();
- add_layoutwidgetbase(button, add_before);
+ add_layoutwidgetbase(button);
//add_view(button); //So it can get the document.
const FieldFormatting::HorizontalAlignment alignment =
@@ -610,16 +591,12 @@ void FlowTableWithFields::add_button_at_position(const sharedptr<LayoutItem_Butt
expand = true;
}
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before(*widget_to_add, *widget, expand);
- else
- add(*widget_to_add, expand);
+ add(*widget_to_add, expand);
apply_formatting(*button, layoutitem_button);
}
-void FlowTableWithFields::add_textobject_at_position(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name , const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_textobject(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name)
{
//Add the widget:
@@ -638,16 +615,12 @@ void FlowTableWithFields::add_textobject_at_position(const sharedptr<LayoutItem_
apply_formatting(*label, layoutitem_text);
- add_layoutwidgetbase(label, add_before);
+ add_layoutwidgetbase(label);
const Glib::ustring title = layoutitem_text->get_title();
if(title.empty())
{
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before(*alignment_label, *widget, true /* expand */);
- else
- add(*alignment_label, true /* expand */);
+ add(*alignment_label, true /* expand */);
}
else
{
@@ -659,17 +632,13 @@ void FlowTableWithFields::add_textobject_at_position(const sharedptr<LayoutItem_
title_label->set_layout_item(layoutitem_text, table_name);
title_label->show();
alignment_title->add(*title_label);
- add_layoutwidgetbase(title_label, add_before);
+ add_layoutwidgetbase(title_label);
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before (*alignment_title, *alignment_label, *widget, true /* expand */);
- else
- add(*alignment_title, *alignment_label, true /* expand */);
+ add(*alignment_title, *alignment_label, true /* expand */);
}
}
-void FlowTableWithFields::add_placeholder_at_position(const sharedptr<LayoutItem_Placeholder>& /* layoutitem_placeholder */, const Glib::ustring& /* table_name */, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_placeholder(const sharedptr<LayoutItem_Placeholder>& /* layoutitem_placeholder */, const Glib::ustring& /* table_name */)
{
//Delete any existing placeholder (there can be only one):
delete m_placeholder;
@@ -685,15 +654,11 @@ void FlowTableWithFields::add_placeholder_at_position(const sharedptr<LayoutItem
m_placeholder->add(*preview);
- m_list_layoutwidgets.insert(add_before, preview);
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before(*m_placeholder, *widget, false /* expand */);
- else
- add(*m_placeholder, false);
+ m_list_layoutwidgets.push_back(preview);
+ add(*m_placeholder, false);
}
-void FlowTableWithFields::add_imageobject_at_position(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name , const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_imageobject(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name)
{
//Add the widget:
ImageGlom* image = Gtk::manage(new ImageGlom());
@@ -703,17 +668,13 @@ void FlowTableWithFields::add_imageobject_at_position(const sharedptr<LayoutItem
image->set_layout_item(layoutitem_image, table_name);
image->show();
- add_layoutwidgetbase(image, add_before);
+ add_layoutwidgetbase(image);
//add_view(button); //So it can get the document.
const Glib::ustring title = layoutitem_image->get_title();
if(title.empty())
{
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before(*image, *widget, true /* expand */);
- else
- add(*image, true /* expand */);
+ add(*image, true /* expand */);
}
else
{
@@ -724,11 +685,7 @@ void FlowTableWithFields::add_imageobject_at_position(const sharedptr<LayoutItem
Gtk::Label* title_label = Gtk::manage(new Gtk::Label(title));
title_label->show();
alignment_title->add(*title_label);
- Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
- if(widget)
- insert_before(*alignment_title, *image, *widget, true /* expand */);
- else
- add(*alignment_title, *image, true /* expand */);
+ add(*alignment_title, *image, true /* expand */);
}
}
@@ -1141,12 +1098,7 @@ void FlowTableWithFields::set_design_mode(bool value)
void FlowTableWithFields::add_layoutwidgetbase(LayoutWidgetBase* layout_widget)
{
- add_layoutwidgetbase(layout_widget, m_list_layoutwidgets.end());
-}
-
-void FlowTableWithFields::add_layoutwidgetbase(LayoutWidgetBase* layout_widget, const type_list_layoutwidgets::iterator& add_before)
-{
- m_list_layoutwidgets.insert(add_before, layout_widget);
+ m_list_layoutwidgets.push_back(layout_widget);
//Handle layout_changed signal:
#ifndef GLOM_ENABLE_CLIENT_ONLY
diff --git a/glom/mode_data/flowtablewithfields.h b/glom/mode_data/flowtablewithfields.h
index 463be08..3ad7bde 100644
--- a/glom/mode_data/flowtablewithfields.h
+++ b/glom/mode_data/flowtablewithfields.h
@@ -228,18 +228,14 @@ private:
typedef std::list< LayoutWidgetBase* > type_list_layoutwidgets;
type_list_layoutwidgets m_list_layoutwidgets;
- void add_field_at_position(const sharedptr<LayoutItem_Field>& layoutitem_field, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
- void add_button_at_position(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
- void add_textobject_at_position(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
- void add_imageobject_at_position(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
- void add_placeholder_at_position(const sharedptr<LayoutItem_Placeholder>& layoutitem_image, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
+ void add_button(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name);
+ void add_textobject(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name);
+ void add_imageobject(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name);
+ void add_placeholder(const sharedptr<LayoutItem_Placeholder>& layoutitem_image, const Glib::ustring& table_name);
void add_layoutwidgetbase(LayoutWidgetBase* layout_widget);
- void add_layoutwidgetbase(LayoutWidgetBase* layout_widget, const type_list_layoutwidgets::iterator& add_before);
- void add_layout_item_at_position(const sharedptr<LayoutItem>& item, const type_list_layoutwidgets::iterator& add_before);
- void add_layout_group_at_position(const sharedptr<LayoutGroup>& group, const type_list_layoutwidgets::iterator& add_before, bool with_indent = true);
- void add_layout_notebook_at_position(const sharedptr<LayoutItem_Notebook>& notebook, const type_list_layoutwidgets::iterator& add_before);
- void add_layout_portal_at_position(const sharedptr<LayoutItem_Portal>& portal, const type_list_layoutwidgets::iterator& add_before);
+ void add_layout_notebook(const sharedptr<LayoutItem_Notebook>& notebook);
+ void add_layout_portal(const sharedptr<LayoutItem_Portal>& portal);
#ifndef GLOM_ENABLE_CLIENT_ONLY
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
index db70787..c7f7e38 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
@@ -30,26 +30,28 @@
#define DEFAULT_LINES 2
#define P_(msgid) (msgid)
+
+enum {
+ PROP_0,
+ PROP_STEAL_EVENTS
+};
+
+
+/* GObjectClass */
+static void egg_spread_table_dnd_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void egg_spread_table_dnd_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
/* GtkWidgetClass */
static void egg_spread_table_dnd_realize (GtkWidget *widget);
-static gboolean egg_spread_table_dnd_motion (GtkWidget *widget,
- GdkEventMotion *event);
-static gboolean egg_spread_table_dnd_leave (GtkWidget *widget,
- GdkEventCrossing *event);
-static gboolean egg_spread_table_dnd_button_press (GtkWidget *widget,
- GdkEventButton *event);
-static gboolean egg_spread_table_dnd_button_release (GtkWidget *widget,
- GdkEventButton *event);
static void egg_spread_table_dnd_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
-/* GtkWidgetClass drag-source */
-static void egg_spread_table_dnd_drag_data_get (GtkWidget *widget,
- GdkDragContext *context,
- GtkSelectionData *selection_data,
- guint info,
- guint time_);
-
/* GtkWidgetClass drag-dest */
static void egg_spread_table_dnd_drag_leave (GtkWidget *widget,
GdkDragContext *context,
@@ -77,7 +79,7 @@ static void egg_spread_table_dnd_remove (GtkContainer
GtkWidget *child);
/* EggSpreadTableClass */
-static void egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
+static void egg_spread_table_dnd_insert_child_impl (EggSpreadTable *spread_table,
GtkWidget *child,
gint index);
static gint egg_spread_table_dnd_build_segments (EggSpreadTable *table,
@@ -106,9 +108,6 @@ static gboolean drag_failed (GtkWidget *widge
GtkDragResult result,
EggSpreadTableDnd *spread_table);
-static GtkWidget *get_child_at_position (EggSpreadTableDnd *spread_table,
- gint x,
- gint y);
static gint get_index_at_position (EggSpreadTableDnd *spread_table,
gint x,
gint y,
@@ -141,21 +140,15 @@ struct _EggSpreadTableDndPrivate {
/* After successfully calling gtk_drag_get_data(), the drag data ends up in this struct */
EggSpreadTableDndDragData drag_data;
- GtkWidget *drag_child; /* If the drag started on a widget with no window, then the spread table
- * keeps a hold on which child is being dragged */
-
- guint dragging : 1; /* Whether the drag'n'drop operation is currently active over this table */
+ GtkWidget *drag_child; /* If the drag started on a widget with no window, then the spread table
+ * keeps a hold on which child is being dragged */
- gint disappearing; /* Count of placeholders that are currently disappearing */
-
- /* These states are used to trigger a drag operation on a child widget with no window */
- gint pressed_button;
- gint press_start_x;
- gint press_start_y;
-
- /* Caching and locking the child configuration */
- gint *locked_config;
+ guint dragging : 1; /* Whether the drag'n'drop operation is currently active over this table */
+ guint steal_events : 1; /* Whether to steal all child events (causes the event-boxes to
+ * place thier event window above all children) */
+ gint disappearing; /* Count of placeholders that are currently disappearing */
+ gint *locked_config; /* Caching and locking the child configuration */
};
@@ -164,6 +157,7 @@ enum {
LAST_SIGNAL
};
+static GQuark dnd_table_child_quark = 0;
static guint dnd_table_signals [LAST_SIGNAL] = { 0 };
static GdkAtom dnd_target_atom_child = GDK_NONE;
static const GtkTargetEntry dnd_targets[] = {
@@ -177,33 +171,44 @@ G_DEFINE_TYPE (EggSpreadTableDnd, egg_spread_table_dnd, EGG_TYPE_SPREAD_TABLE)
static void
egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
EggSpreadTableClass *spread_class = EGG_SPREAD_TABLE_CLASS (class);
- widget_class->realize = egg_spread_table_dnd_realize;
- widget_class->button_press_event = egg_spread_table_dnd_button_press;
- widget_class->button_release_event = egg_spread_table_dnd_button_release;
- widget_class->motion_notify_event = egg_spread_table_dnd_motion;
- widget_class->leave_notify_event = egg_spread_table_dnd_leave;
+ gobject_class->get_property = egg_spread_table_dnd_get_property;
+ gobject_class->set_property = egg_spread_table_dnd_set_property;
- widget_class->size_allocate = egg_spread_table_dnd_size_allocate;
+ widget_class->realize = egg_spread_table_dnd_realize;
+ widget_class->size_allocate = egg_spread_table_dnd_size_allocate;
+ widget_class->drag_leave = egg_spread_table_dnd_drag_leave;
+ widget_class->drag_motion = egg_spread_table_dnd_drag_motion;
+ widget_class->drag_drop = egg_spread_table_dnd_drag_drop;
+ widget_class->drag_data_received = egg_spread_table_dnd_drag_data_received;
- /* Drag source */
- widget_class->drag_data_get = egg_spread_table_dnd_drag_data_get;
+ container_class->remove = egg_spread_table_dnd_remove;
- /* Drag dest */
- widget_class->drag_leave = egg_spread_table_dnd_drag_leave;
- widget_class->drag_motion = egg_spread_table_dnd_drag_motion;
- widget_class->drag_drop = egg_spread_table_dnd_drag_drop;
- widget_class->drag_data_received = egg_spread_table_dnd_drag_data_received;
+ spread_class->insert_child = egg_spread_table_dnd_insert_child_impl;
+ spread_class->build_segments_for_size = egg_spread_table_dnd_build_segments;
- container_class->remove = egg_spread_table_dnd_remove;
+ class->widget_drop_possible = egg_spread_table_dnd_drop_possible;
- spread_class->insert_child = egg_spread_table_dnd_insert_child;
- spread_class->build_segments_for_size = egg_spread_table_dnd_build_segments;
+ /**
+ * EggSpreadTableDnd:steal-events:
+ *
+ * Whether the table should steal all pointer events from added children
+ * for the purpose of Drag'n'Drop.
+ *
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_STEAL_EVENTS,
+ g_param_spec_boolean ("steal-events",
+ P_("Steal Events"),
+ P_("Whether the table should steal all pointer "
+ "events from children"),
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
- class->widget_drop_possible = egg_spread_table_dnd_drop_possible;
/**
* EggSpreadTableDnd::widget-drop-possible
@@ -229,6 +234,7 @@ egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
dnd_target_atom_child = gdk_atom_intern_static_string (dnd_targets[0].target);
+ dnd_table_child_quark = g_quark_from_static_string ("egg-spread-table-dnd-child");
g_type_class_add_private (class, sizeof (EggSpreadTableDndPrivate));
}
@@ -241,8 +247,6 @@ egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
spread_table->priv = priv =
G_TYPE_INSTANCE_GET_PRIVATE (spread_table, EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndPrivate);
- priv->pressed_button = -1;
-
/* Setup the spread table as a drag target for our target type */
gtk_drag_dest_set (GTK_WIDGET (spread_table),
0,
@@ -259,6 +263,47 @@ egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
}
/*****************************************************
+ * GObectClass *
+ *****************************************************/
+static void
+egg_spread_table_dnd_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggSpreadTableDnd *table = EGG_SPREAD_TABLE_DND (object);
+
+ switch (prop_id)
+ {
+ case PROP_STEAL_EVENTS:
+ g_value_set_boolean (value, table->priv->steal_events);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_spread_table_dnd_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggSpreadTableDnd *table = EGG_SPREAD_TABLE_DND (object);
+
+ switch (prop_id)
+ {
+ case PROP_STEAL_EVENTS:
+ egg_spread_table_dnd_set_steal_events (table, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/*****************************************************
* GtkWidgetClass *
*****************************************************/
static void
@@ -294,83 +339,6 @@ egg_spread_table_dnd_realize (GtkWidget *widget)
gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
}
-static gboolean
-egg_spread_table_dnd_motion (GtkWidget *widget,
- GdkEventMotion *event)
-{
- EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
-
- if (spread_table->priv->pressed_button >= 0 &&
- gtk_drag_check_threshold (widget,
- spread_table->priv->press_start_x,
- spread_table->priv->press_start_y,
- event->x, event->y))
- {
- spread_table->priv->drag_child =
- get_child_at_position (spread_table,
- spread_table->priv->press_start_x,
- spread_table->priv->press_start_y);
-
- if (spread_table->priv->drag_child)
- {
- gtk_drag_begin (spread_table->priv->drag_child,
- gtk_drag_source_get_target_list (widget),
- GDK_ACTION_MOVE,
- spread_table->priv->pressed_button,
- (GdkEvent*)event);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static gboolean
-egg_spread_table_dnd_leave (GtkWidget *widget,
- G_GNUC_UNUSED GdkEventCrossing *event)
-{
- EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
-
- spread_table->priv->pressed_button = -1;
-
- return TRUE;
-}
-
-static gboolean
-egg_spread_table_dnd_button_press (GtkWidget *widget,
- GdkEventButton *event)
-{
- EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
- gboolean handled = FALSE;
-
- if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
- {
- /* Save press to possibly begin a drag */
- if (get_child_at_position (spread_table, event->x, event->y) &&
- spread_table->priv->pressed_button < 0)
- {
- spread_table->priv->pressed_button = event->button;
- spread_table->priv->press_start_x = event->x;
- spread_table->priv->press_start_y = event->y;
-
- handled = TRUE;
- }
- }
-
- return handled;
-}
-
-static gboolean
-egg_spread_table_dnd_button_release (GtkWidget *widget,
- GdkEventButton *event)
-{
- EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
-
- if (spread_table->priv->pressed_button == (gint)event->button)
- spread_table->priv->pressed_button = -1;
-
- return TRUE;
-}
-
static void
get_widget_size (GtkWidget *widget,
GtkOrientation orientation,
@@ -434,7 +402,7 @@ allocate_child (EggSpreadTableDnd *table,
}
static void
-get_spread_table_dimentions (EggSpreadTableDnd *spread_table,
+get_spread_table_dimensions (EggSpreadTableDnd *spread_table,
gint for_size,
gint *line_spacing,
gint *item_spacing,
@@ -495,7 +463,7 @@ egg_spread_table_dnd_size_allocate (GtkWidget *widget,
parent_parent_class = g_type_class_peek_parent (egg_spread_table_dnd_parent_class);
parent_parent_class->size_allocate (widget, allocation);
- get_spread_table_dimentions (table, -1, &line_spacing, &item_spacing, &full_thickness, &line_thickness);
+ get_spread_table_dimensions (table, -1, &line_spacing, &item_spacing, &full_thickness, &line_thickness);
lines = egg_spread_table_get_lines (EGG_SPREAD_TABLE (table));
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
@@ -537,34 +505,6 @@ egg_spread_table_dnd_size_allocate (GtkWidget *widget,
g_free (segments);
}
-
-/*****************************************************
- * GtkWidgetClass drag source *
- *****************************************************/
-
-static void
-egg_spread_table_dnd_drag_data_get (GtkWidget *widget,
- G_GNUC_UNUSED GdkDragContext *context,
- GtkSelectionData *selection,
- G_GNUC_UNUSED guint info,
- G_GNUC_UNUSED guint time_)
-{
- EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
- EggSpreadTableDndDragData drag_data = { spread_table, NULL };
- GdkAtom target;
-
- target = gtk_selection_data_get_target (selection);
-
- if (spread_table->priv->drag_child &&
- target == dnd_target_atom_child)
- {
- drag_data.child = spread_table->priv->drag_child;
-
- gtk_selection_data_set (selection, target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
- }
-}
-
/*****************************************************
* GtkWidgetClass drag dest *
*****************************************************/
@@ -638,8 +578,8 @@ get_placeholder_size (EggSpreadTableDnd *spread_table,
GtkOrientation orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table));
gint line_width;
- /* Calculate the size of the required placeholder based on the dimentions of the drag widget */
- get_spread_table_dimentions (spread_table, -1, NULL, NULL, NULL, &line_width);
+ /* Calculate the size of the required placeholder based on the dimensions of the drag widget */
+ get_spread_table_dimensions (spread_table, -1, NULL, NULL, NULL, &line_width);
if (orientation == GTK_ORIENTATION_VERTICAL)
{
@@ -716,6 +656,9 @@ egg_spread_table_dnd_drag_motion (GtkWidget *widget,
get_placeholder_size (spread_table, &width, &height);
spread_table->priv->drop_target = egg_placeholder_new (width, height);
+ g_object_set_qdata (G_OBJECT (spread_table->priv->drop_target),
+ dnd_table_child_quark, GINT_TO_POINTER (TRUE));
+
egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
spread_table->priv->drop_target, index);
adjust_line_segment (spread_table, line, 1);
@@ -813,6 +756,14 @@ static void
egg_spread_table_dnd_remove (GtkContainer *container,
GtkWidget *child)
{
+ if (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (child), dnd_table_child_quark)) == FALSE)
+ {
+ g_message ("Refusing to remove child widget from EggSpreadTableDnd directly, "
+ "use egg_spread_table_dnd_remove_child() instead.");
+ return;
+ }
+
+
/* Disconnect dnd */
if (!EGG_IS_PLACEHOLDER (child))
{
@@ -831,10 +782,17 @@ egg_spread_table_dnd_remove (GtkContainer *container,
* EggSpreadTableClass *
*****************************************************/
static void
-egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
- GtkWidget *child,
- gint index)
+egg_spread_table_dnd_insert_child_impl (EggSpreadTable *spread_table,
+ GtkWidget *child,
+ gint index)
{
+ if (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (child), dnd_table_child_quark)) == FALSE)
+ {
+ g_message ("Refusing to add child widget to an EggSpreadTableDnd directly, "
+ "use egg_spread_table_dnd_insert_child() instead.");
+ return;
+ }
+
EGG_SPREAD_TABLE_CLASS (egg_spread_table_dnd_parent_class)->insert_child (spread_table, child, index);
/* Connect dnd */
@@ -874,7 +832,7 @@ egg_spread_table_dnd_build_segments (EggSpreadTable *table,
return EGG_SPREAD_TABLE_CLASS
(egg_spread_table_dnd_parent_class)->build_segments_for_size (table, for_size, segments);
- get_spread_table_dimentions (dnd_table, for_size, NULL, &spacing, NULL, &line_thickness);
+ get_spread_table_dimensions (dnd_table, for_size, NULL, &spacing, NULL, &line_thickness);
children = gtk_container_get_children (GTK_CONTAINER (table));
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
@@ -926,15 +884,56 @@ egg_spread_table_dnd_drop_possible (EggSpreadTableDnd *table,
/*****************************************************
* Drag'n'Drop signals & other functions *
*****************************************************/
+static void
+set_drag_icon (GtkWidget *widget,
+ GdkDragContext *context)
+{
+ GtkAllocation allocation;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ GtkStyleContext *style;
+ GdkPixbuf *pixbuf;
+ gint hot_x, hot_y;
+
+ /* XXX Force allocate here ? need to absolutely have an allocated widget
+ * for this to work (gtk_widget_draw() needs that). */
+
+ gtk_widget_get_allocation (widget, &allocation);
+ gtk_widget_get_pointer (widget, &hot_x, &hot_y);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, allocation.width, allocation.height);
+ cr = cairo_create (surface);
+
+ /* Synthetically render a background */
+ style = gtk_widget_get_style_context (widget);
+ gtk_style_context_save (style);
+ gtk_style_context_add_class (style, GTK_STYLE_CLASS_BACKGROUND);
+ gtk_render_background (style, cr, 0, 0, allocation.width, allocation.height);
+ gtk_style_context_restore (style);
+
+ /* Draw the actual widget, this might or might not draw the background */
+ gtk_widget_draw (widget, cr);
+
+ /* Make a pixbuf and use that (just to take advantage of the 'hot_x'/'hot_y' parameters) */
+ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, allocation.width, allocation.height);
+ gtk_drag_set_icon_pixbuf (context, pixbuf, hot_x, hot_y);
+
+ g_object_unref (pixbuf);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+}
static void
drag_begin (GtkWidget *widget,
- G_GNUC_UNUSED GdkDragContext *context,
+ GdkDragContext *context,
EggSpreadTableDnd *spread_table)
{
GtkAllocation allocation;
gint drop_index;
+ /* Set the icon for the drag */
+ set_drag_icon (widget, context);
+
/* Mark the spread table for an active drag */
lock_table (spread_table);
spread_table->priv->dragging = TRUE;
@@ -950,9 +949,12 @@ drag_begin (GtkWidget *widget,
"position", &drop_index,
NULL);
- /* Create a placeholder of the correct dimentions and insert it at the drag origin */
+ /* Create a placeholder of the correct dimensions and insert it at the drag origin */
gtk_widget_get_allocation (widget, &allocation);
spread_table->priv->drop_target = egg_placeholder_new (allocation.width, allocation.height);
+ g_object_set_qdata (G_OBJECT (spread_table->priv->drop_target),
+ dnd_table_child_quark, GINT_TO_POINTER (TRUE));
+
egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
spread_table->priv->drop_target,
@@ -1031,7 +1033,7 @@ get_index_at_position (EggSpreadTableDnd *spread_table,
lines = egg_spread_table_get_lines (table);
segments = egg_spread_table_get_segments (table);
- get_spread_table_dimentions (spread_table, -1, &spacing, NULL, &full_size, &line_width);
+ get_spread_table_dimensions (spread_table, -1, &spacing, NULL, &full_size, &line_width);
if (orientation == GTK_ORIENTATION_VERTICAL)
position = x;
@@ -1118,38 +1120,6 @@ get_index_at_position (EggSpreadTableDnd *spread_table,
return index;
}
-static GtkWidget *
-get_child_at_position (EggSpreadTableDnd *spread_table,
- gint x,
- gint y)
-{
- GtkWidget *child, *ret_child = NULL;
- GList *children, *l;
- GtkAllocation allocation;
-
- children = gtk_container_get_children (GTK_CONTAINER (spread_table));
-
- for (l = children; ret_child == NULL && l != NULL; l = l->next)
- {
- child = l->data;
-
- if (!gtk_widget_get_visible (child))
- continue;
-
- gtk_widget_get_allocation (child, &allocation);
-
- if (x >= allocation.x && x <= allocation.x + allocation.width &&
- y >= allocation.y && y <= allocation.y + allocation.height)
- {
- ret_child = child;
- }
- }
-
- g_list_free (children);
-
- return ret_child;
-}
-
static gboolean
drop_possible (EggSpreadTableDnd *spread_table,
GtkWidget *widget)
@@ -1248,3 +1218,105 @@ egg_spread_table_dnd_new (GtkOrientation orientation,
"lines", lines,
NULL);
}
+
+/**
+ * egg_spread_table_dnd_insert_child:
+ * @table: An #EggSpreadTableDnd
+ * @child: The child widget to insert.
+ *
+ * Adds a child widget to an #EggSpreadTableDnd.
+ *
+ * <note><para>Regular #GtkContainer apis and #EggSpreadTable
+ * apis are inappropriate for adding children as those
+ * are reserved for internal use by the #EggSpreadTableDnd.</para></note>
+ */
+void
+egg_spread_table_dnd_insert_child (EggSpreadTableDnd *table,
+ GtkWidget *child,
+ gint index)
+{
+ GtkWidget *event_box;
+
+ g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ event_box = gtk_event_box_new ();
+ gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), table->priv->steal_events);
+ g_object_set_qdata (G_OBJECT (event_box), dnd_table_child_quark, GINT_TO_POINTER (TRUE));
+ gtk_widget_show (event_box);
+
+ gtk_container_add (GTK_CONTAINER (event_box), child);
+ egg_spread_table_insert_child (EGG_SPREAD_TABLE (table), event_box, index);
+}
+
+/**
+ * egg_spread_table_dnd_remove_child:
+ * @table: An #EggSpreadTableDnd
+ * @child: The child widget to insert.
+ *
+ * Adds a child widget to an #EggSpreadTableDnd.
+ *
+ * <note><para>Regular #GtkContainer apis and #EggSpreadTable
+ * apis are inappropriate for removing children as those
+ * are reserved for internal use by the #EggSpreadTableDnd.</para></note>
+ */
+void
+egg_spread_table_dnd_remove_child (EggSpreadTableDnd *table,
+ GtkWidget *child)
+{
+ GtkWidget *event_box;
+
+ g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ event_box = gtk_widget_get_parent (child);
+ if (!event_box)
+ {
+ g_message ("Bad hierarchy encountered in %s. The child had no parent.", G_STRFUNC);
+ return;
+ }
+
+ if (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (event_box), dnd_table_child_quark)) == FALSE)
+ {
+ g_message ("Bad hierarchy encountered in %s.", G_STRFUNC);
+ return;
+ }
+
+ /* unparent the user's child and remove the intermediate spread-table owned event-box. */
+ gtk_container_remove (GTK_CONTAINER (event_box), child);
+ gtk_container_remove (GTK_CONTAINER (table), event_box);
+}
+
+static void
+flip_event_windows (GtkEventBox *child,
+ EggSpreadTableDnd *table)
+{
+ /* Besides the internally owned event boxes, only EggPlaceholders can exist
+ * as direct children of the EggSpreadTableDnd */
+ if (GTK_IS_EVENT_BOX (child))
+ gtk_event_box_set_above_child (child, table->priv->steal_events);
+}
+
+void
+egg_spread_table_dnd_set_steal_events (EggSpreadTableDnd *table,
+ gboolean steal_events)
+{
+ g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
+
+ if (table->priv->steal_events != steal_events)
+ {
+ table->priv->steal_events = steal_events;
+
+ gtk_container_forall (GTK_CONTAINER (table), (GtkCallback)flip_event_windows, table);
+
+ g_object_notify (G_OBJECT (table), "steal-events");
+ }
+}
+
+gboolean
+egg_spread_table_dnd_get_steal_events (EggSpreadTableDnd *table)
+{
+ g_return_val_if_fail (EGG_IS_SPREAD_TABLE_DND (table), FALSE);
+
+ return table->priv->steal_events;
+}
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
index 36c323b..dba5dc7 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
@@ -57,9 +57,17 @@ struct _EggSpreadTableDndClass
};
GType egg_spread_table_dnd_get_type (void) G_GNUC_CONST;
-GtkWidget *egg_spread_table_dnd_new (GtkOrientation orientation,
- guint lines);
-
+GtkWidget *egg_spread_table_dnd_new (GtkOrientation orientation,
+ guint lines);
+
+void egg_spread_table_dnd_insert_child (EggSpreadTableDnd *table,
+ GtkWidget *child,
+ gint index);
+void egg_spread_table_dnd_remove_child (EggSpreadTableDnd *table,
+ GtkWidget *child);
+void egg_spread_table_dnd_set_steal_events (EggSpreadTableDnd *table,
+ gboolean steal_events);
+gboolean egg_spread_table_dnd_get_steal_events (EggSpreadTableDnd *table);
G_END_DECLS
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
index 9e418fe..12c3437 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
@@ -238,6 +238,36 @@ SpreadTableDnd::SpreadTableDnd(Gtk::Orientation orientation, guint lines)
{
}
+void SpreadTableDnd::insert_child(Gtk::Widget& child, int index)
+{
+ egg_spread_table_dnd_insert_child(gobj(), child.gobj(), index);
+}
+
+void SpreadTableDnd::remove_child(Gtk::Widget& child)
+{
+ //This is based on Gtk::Container::remove()
+ //We don't need to do this often, because specialized remove() functions are unusual:
+ //
+ //If this is a managed widget,
+ //then do an extra ref so that it will
+ //not be destroyed when adding to another container
+ //This should leave it in much the same state as when it was instantiated,
+ //before being added to the first container.
+ if(child.is_managed_())
+ child.reference();
+
+ egg_spread_table_dnd_remove_child(gobj(), child.gobj());
+}
+
+void SpreadTableDnd::set_steal_events(bool steal_events)
+{
+ egg_spread_table_dnd_set_steal_events(gobj(), steal_events);
+}
+
+bool SpreadTableDnd::get_steal_events() const
+{
+ return egg_spread_table_dnd_get_steal_events(const_cast<EggSpreadTableDnd*>(gobj()));
+}
bool SpreadTableDnd::on_widget_drop_possible(Gtk::Widget* widget)
{
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
index 7d185d3..91c7f03 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
@@ -93,6 +93,11 @@ public:
SpreadTableDnd();
explicit SpreadTableDnd(Gtk::Orientation orientation, guint lines);
+ void insert_child(Gtk::Widget& child, int index);
+ void remove_child(Gtk::Widget& child);
+ void set_steal_events(bool steal_events);
+ bool get_steal_events() const;
+
/**
* @par Prototype:
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h
index 734b18d..c1b5805 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h
@@ -97,7 +97,8 @@ public:
//TODO: Is the default packing appropriate (and like the default for a Box::pack_start())?
- void insert_child(Gtk::Widget& widget, int index);
+ //This is virtual to avoid us needing to override append_child() too in EggSpreadTableDnd
+ virtual void insert_child(Gtk::Widget& widget, int index);
guint get_child_line(const Gtk::Widget& child, int size) const;
diff --git a/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc b/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc
index 5368663..f045f4e 100644
--- a/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc
+++ b/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc
@@ -37,7 +37,7 @@ static bool parent_accepts_drops = true;
static void
-populate_spread_table_wrappy(Egg::SpreadTable* spread_table)
+populate_spread_table_wrappy(Egg::SpreadTableDnd* spread_table)
{
const gchar *strings[] = {
"These are", "some wrappy label", "texts", "of various", "lengths.",
@@ -55,7 +55,7 @@ populate_spread_table_wrappy(Egg::SpreadTable* spread_table)
iter != children.end(); ++iter)
{
Gtk::Widget *child = *iter;
- paper->remove(*child);
+ paper->remove_child(*child);
delete child;
}
diff --git a/glom/utility_widgets/flowtable.cc b/glom/utility_widgets/flowtable.cc
index 6696cd7..6ea612f 100644
--- a/glom/utility_widgets/flowtable.cc
+++ b/glom/utility_widgets/flowtable.cc
@@ -43,41 +43,33 @@ FlowTable::~FlowTable()
}
}
-Gtk::HBox* FlowTable::get_parent_hbox(Gtk::Widget* first)
+const Gtk::HBox* FlowTable::get_parent_hbox(const Gtk::Widget* first) const
{
- typedef std::vector<Widget*> type_children;
- type_children children = get_children();
- for(type_children::iterator iter = children.begin(); iter != children.end(); ++iter)
+ const type_const_list_widgets::const_iterator iter_find =
+ std::find(m_list_first_widgets.begin(), m_list_first_widgets.end(), first);
+ if(iter_find == m_list_first_widgets.end())
{
- Gtk::Widget* widget = *iter;
- if(!widget)
+ std::cerr << G_STRFUNC << ": first was not a first widget. first=" << first << std::endl;
+ return 0; //It has no HBox parent because it is not even a first widget.
+ }
+
+ for(type_list_hboxes::const_iterator iter = m_list_hboxes.begin(); iter != m_list_hboxes.end(); ++iter)
+ {
+ const Gtk::HBox* hbox = *iter;
+ if(!hbox)
continue;
- if(widget == first) //It must be a single item.
- return 0; //It has no HBox parent.
- else
- {
- Gtk::HBox* hbox = dynamic_cast<Gtk::HBox*>(widget);
- if(hbox) //The first and second widgets are inside an HBox
- {
- //Check that it is one of our special HBoxes,
- //though this check should not be neccesary:
- const type_list_hboxes::const_iterator iter_boxes =
- std::find(m_list_hboxes.begin(), m_list_hboxes.end(), hbox);
- if(iter_boxes != m_list_hboxes.end())
- {
- const type_children box_children = hbox->get_children();
- if(!box_children.empty())
- {
- const Gtk::Widget* child_widget = box_children[0]; //TODO: Is this definitely the left-most one?
- if(child_widget == first)
- return hbox;
- }
- }
- }
- }
- }
+ //Check if it has the widget as one of its children:
+ typedef std::vector<const Gtk::Widget*> type_children;
+ const type_children box_children = hbox->get_children();
+ if(box_children.empty())
+ continue;
+ const type_children::const_iterator iter_find =
+ std::find(box_children.begin(), box_children.end(), first);
+ if(iter_find != box_children.end())
+ return hbox;
+ }
return 0;
}
@@ -94,26 +86,33 @@ void FlowTable::delete_and_forget_hbox(Gtk::HBox* hbox)
children = hbox->get_children();
}
- if(hbox->get_parent() == this)
+ //This check does not work because EggSpreadTableDnD adds an intermediate GtkEventBox:
+ //if(hbox->get_parent() == this)
+
+ //Check that it is in our list of hboxes:
+ const type_list_hboxes::iterator iter = std::find(
+ m_list_hboxes.begin(), m_list_hboxes.end(), hbox);
+ if(iter == m_list_hboxes.end())
+ {
+ std::cerr << G_STRFUNC << ": hbox=" << hbox << " is not in our list of hboxes." << std::endl;
+ return;
+ }
+
+ //Check that it has a parent,
+ //as a sanity check:
+ Gtk::Widget* parent= hbox->get_parent();
+ if(parent)
{
- Egg::SpreadTable::remove(*hbox);
+ Egg::SpreadTableDnd::remove_child(*hbox);
}
else
{
- std::cerr << G_STRFUNC << ": hbox is not a direct child." << std::endl;
+ std::cerr << G_STRFUNC << ": hbox=" << hbox << " has no parent. Not removing from SpreadTableDnd" << std::endl;
}
//Delete and forget it:
- for(type_list_hboxes::iterator iter = m_list_hboxes.begin(); iter != m_list_hboxes.end(); ++iter)
- {
- Gtk::HBox* this_hbox = *iter;
- if(hbox == this_hbox)
- {
- delete hbox; //TODO: This causes a warning during gtk_container_remove(), though we have already removed it: sys:1: Warning: g_object_ref: assertion `object->ref_count > 0' failed
- m_list_hboxes.erase(iter);
- return;
- }
- }
+ delete hbox; //TODO: This causes a warning during gtk_container_remove(), though we have already removed it: sys:1: Warning: g_object_ref: assertion `object->ref_count > 0' failed
+ m_list_hboxes.erase(iter);
}
void FlowTable::set_design_mode(bool value)
@@ -145,12 +144,17 @@ void FlowTable::insert(Gtk::Widget* first, Gtk::Widget* second, int index, bool
hbox->show();
hbox->set_halign(Gtk::ALIGN_FILL);
- insert_child(*hbox, index);
+ Egg::SpreadTableDnd::insert_child(*hbox, index);
+ //std::cout << "DEBUG: inserted hbox=" << hbox << " for first=" << first << std::endl;
+
+ m_list_first_widgets.push_back(first);
}
else if(first)
{
first->set_halign(expand ? Gtk::ALIGN_FILL : Gtk::ALIGN_START);
- append_child(*first);
+ Egg::SpreadTableDnd::append_child(*first);
+ //std::cout << "DEBUG: inserted first=" << first << std::endl;
+ m_list_first_widgets.push_back(first);
}
else
{
@@ -158,78 +162,52 @@ void FlowTable::insert(Gtk::Widget* first, Gtk::Widget* second, int index, bool
}
}
-int FlowTable::get_child_index(const Gtk::Widget& first) const
+void FlowTable::remove_all()
{
- int index = 0;
-
- typedef std::vector<const Widget*> type_children;
- const type_children children = get_children();
- for(type_children::const_iterator iter = children.begin(); iter != children.end(); ++iter)
+ for(type_const_list_widgets::const_iterator iter = m_list_first_widgets.begin(); iter != m_list_first_widgets.end(); ++iter)
{
- const Gtk::Widget* widget = *iter;
- if(!widget)
- continue;
-
- if(widget == &first) //It must be a single item.
- break;
- else
- {
- const Gtk::HBox* hbox = dynamic_cast<const Gtk::HBox*>(widget);
- if(hbox) //The first and second widgets are inside an HBox
- {
- const type_children box_children = hbox->get_children();
- if(!box_children.empty())
- {
- const Gtk::Widget* child_widget = box_children[0]; //TODO: Is this definitely the left-most one?
- if(child_widget == &first)
- break;
- }
- }
- }
-
- ++index;
+ Gtk::Widget* first_widget = const_cast<Gtk::Widget*>(*iter);
+
+ if(first_widget)
+ remove(*first_widget);
}
+ m_list_first_widgets.clear();
- return index;
-}
-
-void FlowTable::insert_before(Gtk::Widget& first, Gtk::Widget& before, bool expand)
-{
- const int index = get_child_index(before);
- insert(&first, 0 /* second */, index - 1, expand);
-}
-
-void FlowTable::insert_before(Gtk::Widget& first, Gtk::Widget& second, Gtk::Widget& before, bool expand_second)
-{
- const int index = get_child_index(before);
- insert(&first, &second, index - 1, expand_second);
-}
-
-void FlowTable::remove_all()
-{
+ //We can't use get_children() because EggSpreadTableDnd does not allow that,
+ //because it handles children differently via its specific API.
+ /*
typedef std::vector<Widget*> type_children;
- type_children children = get_children();
- while(!children.empty())
+ const type_children children = get_children();
+ for(type_children::iterator iter = children.begin(); iter != children.end(); ++iter)
{
- Gtk::Widget* widget = children[0];
+ Gtk::Widget* widget = *iter;
remove(*widget);
- children = get_children();
}
+ */
}
void FlowTable::remove(Gtk::Widget& first)
{
+ //std::cout << G_STRFUNC << ": debug: remove() first=" << &first << std::endl;
+
//Handle widgets that were added to an HBox:
- Gtk::HBox* parent = get_parent_hbox(&first);
+ Gtk::HBox* parent = const_cast<Gtk::HBox*>(get_parent_hbox(&first));
if(parent)
{
+ //std::cout << " debug: hbox=" << parent << std::endl;
+
delete_and_forget_hbox(parent);
return;
}
- Egg::SpreadTable::remove(first);
+ Egg::SpreadTableDnd::remove_child(first);
}
+FlowTable::type_const_list_widgets FlowTable::get_first_child_widgets() const
+{
+ return m_list_first_widgets;
+}
+
bool FlowTable::get_column_for_first_widget(const Gtk::Widget& first, guint& column) const
{
//Initialize output parameter:
@@ -238,46 +216,40 @@ bool FlowTable::get_column_for_first_widget(const Gtk::Widget& first, guint& col
if(get_lines() == 0)
return false;
- typedef std::vector<const Widget*> type_children;
- const type_children children = get_children();
- for(type_children::const_iterator iter = children.begin(); iter != children.end(); ++iter)
- {
- const Gtk::Widget* widget = *iter;
- if(!widget)
- continue;
-
- //Get the widget that EggSpreadTable thinks of as the child:
- const Gtk::Widget* child = 0;
-
- if(widget == &first) //It must be a single item.
- child = widget;
- else
- {
- const Gtk::HBox* hbox = dynamic_cast<const Gtk::HBox*>(widget);
- if(hbox) //The first and second widgets are inside an HBox
- {
- const type_children box_children = hbox->get_children();
- if(!box_children.empty())
- {
- const Gtk::Widget* child_widget = box_children[0]; //TODO: Is this definitely the left-most one?
- if(child_widget == &first)
- child = hbox;
- }
- }
-
- if(child)
- {
- int width_min = 0;
- int width_natural = 0;
- child->get_preferred_width(width_min, width_natural);
- column = get_child_line(*child, width_natural);
-
- return true;
- }
- }
- }
+ //Discover actual child widget that was added to the EggSpreadTable,
+ //so we can use it again to call EggSpreadTable::get_child_line():
+ const Gtk::Widget* child = 0;
+
+ //Check that it is really a child widget:
+ const type_const_list_widgets::const_iterator iter_find =
+ std::find(m_list_first_widgets.begin(), m_list_first_widgets.end(), &first);
+ if(iter_find == m_list_first_widgets.end())
+ return false; //It is not a first widget.
+
+ child = &first;
+
+ //Check if it was added to an HBox:
+ const Gtk::HBox* hbox = get_parent_hbox(child);
+ if(hbox)
+ child = hbox;
+
+ if(!child)
+ return false;
- return false;
+ int width_min = 0;
+ int width_natural = 0;
+ child->get_preferred_width(width_min, width_natural);
+ //std::cout << G_STRFUNC << ": Calling get_child_line() with child=" << child << ", for first=" << &first << std::endl;
+
+ //Get the internal parent GtkEventBox, if any,
+ //though we need a derived get_child_line() to do this automatically:
+ const Gtk::Widget* parent = child->get_parent();
+ if(dynamic_cast<const Gtk::EventBox*>(parent))
+ child = parent;
+
+ column = get_child_line(*child, width_natural);
+
+ return true;
}
} //namespace Glom
diff --git a/glom/utility_widgets/flowtable.h b/glom/utility_widgets/flowtable.h
index df1c95c..b2b290f 100644
--- a/glom/utility_widgets/flowtable.h
+++ b/glom/utility_widgets/flowtable.h
@@ -38,9 +38,7 @@ public:
virtual void add(Gtk::Widget& first, Gtk::Widget& second, bool expand_second = false);
virtual void add(Gtk::Widget& first, bool expand = false); //override
- void insert_before(Gtk::Widget& first, Gtk::Widget& second, Gtk::Widget& before, bool expand_second);
- void insert_before(Gtk::Widget& first, Gtk::Widget& before, bool expand);
-
+
/** Show extra UI that is useful in RAD tools:
*/
virtual void set_design_mode(bool value = true);
@@ -58,10 +56,16 @@ protected:
void insert(Gtk::Widget* first, Gtk::Widget* second, int index, bool expand);
+ typedef std::list<const Gtk::Widget*> type_const_list_widgets;
+
+ /** This returns all first widgets added with FlowTable::add().
+ * Gtk::Container::get_children() instead returns internal widgets.
+ */
+ type_const_list_widgets get_first_child_widgets() const;
+
private:
- int get_child_index(const Gtk::Widget& first) const;
- Gtk::HBox* get_parent_hbox(Gtk::Widget* first);
+ const Gtk::HBox* get_parent_hbox(const Gtk::Widget* first) const;
void delete_and_forget_hbox(Gtk::HBox* hbox);
bool m_design_mode;
@@ -72,6 +76,8 @@ private:
//We remember the HBoxes so we can delete them when the are no longer used.
typedef std::list<Gtk::HBox*> type_list_hboxes;
type_list_hboxes m_list_hboxes;
+
+ type_const_list_widgets m_list_first_widgets;
};
} //namespace Glom
diff --git a/po/ChangeLog b/po/ChangeLog
index 423fcd0..24a1510 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,9 @@
+2011-09-01 Murray Cumming <murrayc murrayc-desktop>
+
+ reviewed by: <delete if not using a buddy>
+
+ * POTFILES.in:
+
2011-08-29 Murray Cumming <murrayc murrayc-desktop>
reviewed by: <delete if not using a buddy>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 553e4b6..3d3fcb4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -125,6 +125,7 @@ glom/utility_widgets/dialog_image_load_progress.cc
glom/utility_widgets/dialog_image_save_progress.cc
glom/mode_data/datawidget/entry.cc
glom/utility_widgets/eggspreadtable/eggspreadtable.c
+glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
glom/utility_widgets/filechooserdialog_saveextras.cc
glom/utility_widgets/imageglom.cc
glom/utility_widgets/layouttoolbar.cc
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]