glom r1529 - in trunk: . glom/mode_data glom/utility_widgets
- From: jhs svn gnome org
- To: svn-commits-list gnome org
- Subject: glom r1529 - in trunk: . glom/mode_data glom/utility_widgets
- Date: Mon, 7 Apr 2008 14:06:54 +0100 (BST)
Author: jhs
Date: Mon Apr 7 14:06:53 2008
New Revision: 1529
URL: http://svn.gnome.org/viewvc/glom?rev=1529&view=rev
Log:
2008-04-07 Johannes Schmid <johannes schmid openismus com>
* glom/mode_data/flowtablewithfields.h:
Derive from FlowTableDnd if not in CLIENT_ONLY mode
* glom/utility_widgets/flowtable.cc:
(dnd_*) (on_dnd_*)
* glom/utility_widgets/flowtable.h:
* glom/utility_widgets/Makefile.am:
* glom/utility_widgets/flowtable_dnd.cc:
* glom/utility_widgets/flowtable_dnd.h:
Moved drag and drop stuff into it\'s own class and some code cleanup
Added:
trunk/glom/utility_widgets/flowtable_dnd.cc
trunk/glom/utility_widgets/flowtable_dnd.h
Modified:
trunk/ChangeLog
trunk/glom/mode_data/flowtablewithfields.h
trunk/glom/utility_widgets/Makefile.am
trunk/glom/utility_widgets/flowtable.h
Modified: trunk/glom/mode_data/flowtablewithfields.h
==============================================================================
--- trunk/glom/mode_data/flowtablewithfields.h (original)
+++ trunk/glom/mode_data/flowtablewithfields.h Mon Apr 7 14:06:53 2008
@@ -23,7 +23,11 @@
#include "config.h" // For GLOM_ENABLE_CLIENT_ONLY
+#ifdef GLOM_ENABLE_CLIENT_ONLY
#include <glom/utility_widgets/flowtable.h>
+#else
+#include <glom/utility_widgets/flowtable_dnd.h>
+#endif
#include <glom/libglom/data_structure/layout/layoutgroup.h>
#include <glom/libglom/data_structure/layout/layoutitem_field.h>
#include <glom/libglom/data_structure/layout/layoutitem_notebook.h>
@@ -46,7 +50,12 @@
class DataWidget;
class FlowTableWithFields
- : public FlowTable,
+ :
+#ifdef GLOM_ENABLE_CLIENT_ONLY
+ public FlowTable,
+#else
+ public FlowTableDnd,
+#endif
public View_Composite_Glom,
public LayoutWidgetBase,
public LayoutWidgetUtils
Modified: trunk/glom/utility_widgets/Makefile.am
==============================================================================
--- trunk/glom/utility_widgets/Makefile.am (original)
+++ trunk/glom/utility_widgets/Makefile.am Mon Apr 7 14:06:53 2008
@@ -37,7 +37,8 @@
checkglom.h checkglom.cc \
layoutwidgetutils.h layoutwidgetutils.cc \
dialog_layoutitem_properties.cc dialog_layoutitem_properties.h \
- dialog_flowtable.cc dialog_flowtable.h
+ dialog_flowtable.cc dialog_flowtable.h \
+ flowtable_dnd.h flowtable_dnd.cc
if !GLOM_ENABLE_CLIENT_ONLY
libutility_widgets_a_SOURCES += filechooserdialog_saveextras.cc filechooserdialog_saveextras.h \
Modified: trunk/glom/utility_widgets/flowtable.h
==============================================================================
--- trunk/glom/utility_widgets/flowtable.h (original)
+++ trunk/glom/utility_widgets/flowtable.h Mon Apr 7 14:06:53 2008
@@ -89,29 +89,6 @@
virtual void on_unrealize();
virtual bool on_expose_event(GdkEventExpose* event);
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- //DND stuff:
- virtual bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time);
- virtual void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time);
- virtual void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, const Gtk::SelectionData& selection_data, guint, guint time);
- virtual void on_dnd_add_placeholder(LayoutWidgetBase* above) = 0;
- virtual void on_dnd_remove_placeholder() = 0;
-
- virtual bool on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time, Gtk::Widget* child);
- virtual void on_child_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time);
- virtual void on_child_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int,
- const Gtk::SelectionData& selection_data, guint, guint time, Gtk::Widget* child);
- void setup_dnd (Gtk::Widget& child);
-
- // Methods for the different layout object
- virtual void on_dnd_add_layout_item_field (LayoutWidgetBase* above) = 0;
- virtual void on_dnd_add_layout_group(LayoutWidgetBase* above) = 0;
- virtual void on_dnd_add_layout_item_button (LayoutWidgetBase* above) = 0;
- virtual void on_dnd_add_layout_item_text (LayoutWidgetBase* above) = 0;
- virtual void on_dnd_add_layout_notebook (LayoutWidgetBase* above) = 0;
-
-#endif // !GLOM_ENABLE_CLIENT_ONLY
-
int get_column_height(guint start_widget, guint widget_count, int& total_width) const;
/**
@@ -147,18 +124,6 @@
void get_item_requested_width(const FlowTableItem& item, int& first, int& second) const;
void get_item_max_width_requested(guint start, guint height, guint& first_max_width, guint& second_max_width, guint& singles_max_width, bool& is_last_column) const; //TODO: maybe combine this with code in get_minimum_column_height().
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- FlowTableItem* dnd_get_item(int x, int y);
- void change_dnd_status(bool active = true);
- LayoutWidgetBase* dnd_find_datawidget();
- FlowTableItem* m_current_dnd_item;
-
- void dnd_remove_placeholder_idle();
- bool dnd_remove_placeholder_real();
-
- bool m_dnd_in_progress;
-#endif // !GLOM_ENABLE_CLIENT_ONLY
-
bool child_is_visible(const Gtk::Widget* widget) const;
Gtk::Allocation assign_child(Gtk::Widget* widget, int x, int y);
@@ -178,6 +143,9 @@
//For drawing:
Glib::RefPtr<Gdk::Window> m_refGdkWindow;
Glib::RefPtr<Gdk::GC> m_refGC;
+
+ // Dnd
+ virtual void setup_dnd (Gtk::Widget& child);
};
} //namespace Glom
Added: trunk/glom/utility_widgets/flowtable_dnd.cc
==============================================================================
--- (empty file)
+++ trunk/glom/utility_widgets/flowtable_dnd.cc Mon Apr 7 14:06:53 2008
@@ -0,0 +1,310 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "flowtable_dnd.h"
+#include "eggtoolpalette/eggtoolpalette.h"
+#include "placeholder-glom.h"
+#include "dragbutton.h"
+#include "entryglom.h"
+#include "labelglom.h"
+#include "buttonglom.h"
+#include "imageglom.h"
+
+namespace Glom
+{
+
+FlowTableDnd::FlowTableDnd() :
+ m_current_dnd_item(0)
+{
+ std::list<Gtk::TargetEntry> drag_targets;
+ Gtk::TargetEntry drag_target(egg_tool_palette_get_drag_target_item());
+ drag_targets.push_back(drag_target);
+ drag_dest_set(drag_targets);
+}
+
+FlowTableDnd::~FlowTableDnd()
+{
+
+}
+
+void FlowTableDnd::setup_dnd (Gtk::Widget& child)
+{
+ if (dynamic_cast<PlaceholderGlom*>(&child) ||
+ dynamic_cast<FlowTableDnd*>(&child))
+ return;
+
+ // Call this method recursive for all (real) children
+ Gtk::Container* container = dynamic_cast<Gtk::Container*>(&child);
+ if (container)
+ {
+ typedef Glib::ListHandle<Gtk::Widget*>::const_iterator CI;
+ Glib::ListHandle<Gtk::Widget*> children = container->get_children();
+ for (CI cur_child = children.begin(); cur_child != children.end();
+ ++cur_child)
+ {
+ setup_dnd (*(*cur_child));
+ }
+ }
+ if (!(child.get_flags() & Gtk::NO_WINDOW))
+ {
+ std::list<Gtk::TargetEntry> new_targets;
+ new_targets.push_back(Gtk::TargetEntry(egg_tool_palette_get_drag_target_item()));
+ Glib::RefPtr<Gtk::TargetList> targets =
+ child.drag_dest_get_target_list ();
+ // The widget has already a default drag destination - add more targets
+ if (targets)
+ {
+ targets->add (new_targets);
+ child.drag_dest_set_target_list (targets);
+ }
+ else
+ child.drag_dest_set(new_targets, Gtk::DEST_DEFAULT_ALL,
+ Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
+
+ // It's important to connect this one BEFORE
+ child.signal_drag_motion().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_motion), &child),
+ false);
+ child.signal_drag_data_received().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_data_received), &child));
+ child.signal_drag_leave().connect (sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_leave));
+ }
+}
+
+bool FlowTableDnd::on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time)
+{
+ // The drag position is relativ to the toplevel GdkWindow and not to
+ // the widget position. We fix this here to match the widget position
+ x += get_allocation().get_x();
+ y += get_allocation().get_y();
+
+ m_current_dnd_item = dnd_item_at_position(x, y);
+ LayoutWidgetBase* above = dnd_datawidget_from_item();
+
+ // above might be 0 here...
+ on_dnd_add_placeholder(above);
+ return false;
+}
+
+void FlowTableDnd::on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int drag_x, int drag_y, const Gtk::SelectionData& selection_data, guint, guint time)
+{
+ Gtk::Widget* palette = drag_get_source_widget (drag_context);
+ while (palette && !EGG_IS_TOOL_PALETTE (palette->gobj()))
+ palette = palette->get_parent();
+ if (palette)
+ {
+ GtkWidget* tool_item = egg_tool_palette_get_drag_item (EGG_TOOL_PALETTE (palette->gobj()), selection_data.gobj());
+ LayoutWidgetBase::enumType type =
+ static_cast<LayoutWidgetBase::enumType>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tool_item), "glom-type")));
+ on_dnd_remove_placeholder();
+ LayoutWidgetBase* above = dnd_datawidget_from_item();
+ switch (type)
+ {
+ case LayoutWidgetBase::TYPE_FIELD:
+ on_dnd_add_layout_item_field(above);
+ break;
+ case LayoutWidgetBase::TYPE_BUTTON:
+ on_dnd_add_layout_item_button(above);
+ break;
+ case LayoutWidgetBase::TYPE_TEXT:
+ on_dnd_add_layout_item_text(above);
+ break;
+ case LayoutWidgetBase::TYPE_GROUP:
+ on_dnd_add_layout_group(above);
+ break;
+ case LayoutWidgetBase::TYPE_NOTEBOOK:
+ on_dnd_add_layout_notebook(above);
+ break;
+ default:
+ std::cerr << "Unknown drop type: " << type << std::endl;
+ }
+ }
+}
+
+void FlowTableDnd::on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time)
+{
+ dnd_remove_placeholder_idle();
+}
+
+// Calculate the nearest FlowTableDndItem below the current drag position
+FlowTable::FlowTableItem*
+FlowTableDnd::dnd_item_at_position(int drag_x, int drag_y)
+{
+ int column_width;
+ get_column_height (0, m_children.size(), column_width);
+ int column = 0;
+
+ if (column_width != 0)
+ column = drag_x / column_width;
+
+ for (std::vector<FlowTableItem>::iterator cur_item = m_children.begin(); cur_item != m_children.end();
+ cur_item++)
+ {
+ Gdk::Rectangle rect = cur_item->m_first->get_allocation();
+ if (cur_item->m_second)
+ {
+ Gdk::Rectangle second_rect = cur_item->m_second->get_allocation();
+ rect.set_height (MAX (rect.get_height(), second_rect.get_height()));
+ rect.set_width (rect.get_width() + m_padding + second_rect.get_width());
+ }
+
+ int cur_column = rect.get_x() / column_width;
+
+ if (cur_column != column)
+ {
+ continue;
+ }
+
+ // Allow dragging at the end
+ if (cur_item == --m_children.end())
+ {
+ if (drag_y > (rect.get_y() + rect.get_height() / 2) &&
+ drag_y < (rect.get_y() + rect.get_height()))
+ {
+ return 0;
+ }
+ }
+
+ if (drag_y < (rect.get_y() + rect.get_height()))
+ {
+ return &(*cur_item);
+ }
+ }
+
+ return 0;
+}
+
+LayoutWidgetBase* FlowTableDnd::dnd_datawidget_from_item()
+{
+ // Test if we have a datawidget below which we want to add
+ LayoutWidgetBase* above = 0;
+ if(m_current_dnd_item)
+ {
+ if(m_current_dnd_item->m_first)
+ {
+ Gtk::Alignment* alignment = dynamic_cast <Gtk::Alignment*>(m_current_dnd_item->m_first);
+ if (alignment)
+ {
+ above = dynamic_cast<LayoutWidgetBase*>(alignment->get_child());
+ }
+ }
+ if(!above && m_current_dnd_item->m_first)
+ above = dynamic_cast<LayoutWidgetBase*>(m_current_dnd_item->m_first);
+ if(!above && m_current_dnd_item->m_second)
+ {
+ above = dynamic_cast<LayoutWidgetBase*>(m_current_dnd_item->m_second);
+ // Special case for labels
+ if (!above)
+ {
+ Gtk::Alignment* alignment = dynamic_cast <Gtk::Alignment*>(m_current_dnd_item->m_second);
+ if (alignment)
+ {
+ above = dynamic_cast<LayoutWidgetBase*>(alignment->get_child());
+ }
+ }
+ }
+ }
+ return above;
+}
+
+bool FlowTableDnd::on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time,
+ Gtk::Widget* child)
+{
+ type_vecChildren::iterator cur_child;
+ for (cur_child = m_children.begin();
+ cur_child != m_children.end(); cur_child++)
+ {
+ // The widget was added directly to the FlowTableDnd
+ if (cur_child->m_first == child ||
+ cur_child->m_second == child)
+ {
+ break;
+ }
+ // The parent of the widget was added to the FlowTableDnd
+ else if (cur_child->m_first == child->get_parent() ||
+ cur_child->m_second == child->get_parent())
+ {
+ break;
+ }
+ Gtk::Bin* bin = dynamic_cast<Gtk::Bin*>(cur_child->m_second);
+ // The widget was added inside a Gtk::EventBox
+ if (bin)
+ {
+ if (bin->get_child() == child ||
+ bin->get_child() == child->get_parent())
+ break;
+ }
+ }
+ if (cur_child != m_children.end())
+ m_current_dnd_item = &(*cur_child);
+ else
+ m_current_dnd_item = 0;
+
+ // Allow dragging at-the-end
+ if (cur_child == --m_children.end())
+ {
+ Gdk::Rectangle rect = child->get_allocation();
+ if (y > (rect.get_y() + rect.get_height() / 2) &&
+ y < (rect.get_y() + rect.get_height()))
+ {
+ m_current_dnd_item = 0; // means end
+ }
+ }
+ on_dnd_remove_placeholder ();
+
+ LayoutWidgetBase* above = dnd_datawidget_from_item();
+
+ // above might be 0 here...
+ on_dnd_add_placeholder(above);
+ return false;
+}
+
+void FlowTableDnd::on_child_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time)
+{
+ dnd_remove_placeholder_idle();
+}
+
+void FlowTableDnd::on_child_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y,
+ const Gtk::SelectionData& selection_data, guint info, guint time,
+ Gtk::Widget* child)
+{
+ on_drag_data_received (drag_context, x, y, selection_data, info, time);
+}
+
+/* This is a hack. The problem is that when you move the mouse down to the last
+ item, the item gets the "drag-motion" signal but in the same moment, the placeholder
+ is removed and the mouse pointer is no longer over the widget. Thus, it gets
+ a "drag-leave" signal and it's impossible to drop an item at the end. Doing
+ the removal of the placeholder in an idle handler fixes it. */
+
+void FlowTableDnd::dnd_remove_placeholder_idle()
+{
+ static sigc::connection connection;
+ if (connection)
+ connection.disconnect();
+ Glib::signal_idle().connect( sigc::mem_fun(*this, &FlowTableDnd::dnd_remove_placeholder_real) );
+}
+
+bool FlowTableDnd::dnd_remove_placeholder_real()
+{
+ on_dnd_remove_placeholder();
+ queue_draw();
+ return false; // remove from idle source
+}
+
+} // namspace Glom
Added: trunk/glom/utility_widgets/flowtable_dnd.h
==============================================================================
--- (empty file)
+++ trunk/glom/utility_widgets/flowtable_dnd.h Mon Apr 7 14:06:53 2008
@@ -0,0 +1,73 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_UTILITYWIDGETS_FLOWTABLE_DND_H
+#define GLOM_UTILITYWIDGETS_FLOWTABLE_DND_H
+
+#include <gtkmm.h>
+#include "flowtable.h"
+
+#ifdef GLOM_ENABLE_CLIENT_ONLY
+#error FlowTableDnd does not work in Client-only mode
+#endif
+
+namespace Glom
+{
+
+class FlowTableDnd : public FlowTable
+{
+public:
+ FlowTableDnd();
+ ~FlowTableDnd();
+
+protected:
+ virtual bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time);
+ virtual void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time);
+ virtual void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, const Gtk::SelectionData& selection_data, guint, guint time);
+
+ virtual bool on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time, Gtk::Widget* child);
+ virtual void on_child_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time);
+ virtual void on_child_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int,
+ const Gtk::SelectionData& selection_data, guint, guint time, Gtk::Widget* child);
+ virtual void setup_dnd (Gtk::Widget& child); // overwritten
+
+ // Methods for the different layout object
+ virtual void on_dnd_add_layout_item_field (LayoutWidgetBase* above) = 0;
+ virtual void on_dnd_add_layout_group(LayoutWidgetBase* above) = 0;
+ virtual void on_dnd_add_layout_item_button (LayoutWidgetBase* above) = 0;
+ virtual void on_dnd_add_layout_item_text (LayoutWidgetBase* above) = 0;
+ virtual void on_dnd_add_layout_notebook (LayoutWidgetBase* above) = 0;
+
+ virtual void on_dnd_add_placeholder(LayoutWidgetBase* above) = 0;
+ virtual void on_dnd_remove_placeholder() = 0;
+
+ void dnd_remove_placeholder_idle();
+ bool dnd_remove_placeholder_real();
+
+ FlowTableItem* dnd_item_at_position(int x, int y);
+ LayoutWidgetBase* dnd_datawidget_from_item();
+
+private:
+ FlowTableItem* m_current_dnd_item;
+};
+
+} // namespace Glom
+
+#endif // GLOM_UTILITYWIDGETS_FLOWTABLE_DND_H
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]