Problem
Suppose you would like to allow users to select items by drag-and-drop from the table on the left to the list on the right as shown below:
Solution
You can add in drag-and-drop support using exactly the same technique as outlined in the article How to drag and drop between 2 GtkTreeViews - Part 1 - left to right?
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 43 44 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 145 147 148 149 150 151 152 153 155 156 157 158 159 | <?php $window = new GtkWindow(); $window->set_size_request(400, 200); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Drag and Drop between a table and a list - Part 1"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 40); $vbox->pack_start($title, 0, 0); // setup table $table = new GtkTable(); $data = array( array('', 'header1', 'header2', 'header3'), array('row0', 1, 2, 3), array('row1', 4, 5, 6), array('row2', 7, 8, 9), array('row3', 10, 11, 12), array('row4', 13, 14, 15)); display_table ($table, $data); $hbox = new GtkHBox(); $vbox->pack_start($hbox); $hbox->pack_start($table, 0, 0); $hbox->pack_start(new GtkLabel(' '), 0 ,0); // setup treeview $data2 = array(); $view2 = display_treeview($hbox, $data2); $view2->drag_dest_set(Gtk::DEST_DEFAULT_ALL, array( array( 'text/plain', 0, 0)), Gdk::ACTION_COPY|Gdk::ACTION_MOVE); // note 2 $view2->connect('drag-data-received', 'on_drop', $table); // note 2 $window->show_all(); Gtk::main(); function display_table($table, $a) { for ($row=0; $row<count($a); ++$row) { for ($col=0; $col<count($a[$row]); ++$col) { $frame = new GtkFrame(); // note 1 $eventbox = new GtkEventBox(); // note 2 $frame->add($eventbox); // note 3 $label = new GtkLabel($a[$row][$col]); $eventbox->add($label); // note 4 if ($row==0) { // note 5 $eventbox->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse("#FFCC66")); } elseif ($row%2==0) { // note 6 $eventbox->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse("#CCFF99")); } $table->attach($frame, $col, $col+1, $row, $row+1, Gtk::FILL, Gtk::SHRINK, 0, 0); $eventbox->drag_source_set(Gdk::BUTTON1_MASK, array( array( 'text/plain', 0, 0)), Gdk::ACTION_COPY|Gdk::ACTION_MOVE); // note 1 $eventbox->connect('drag-data-get', 'on_drag', $row, $col, $a[$row][$col]); // note 1 } } } function display_treeview($container, $data) { // Set up a scroll window $scrolled_win = new GtkScrolledWindow(); $scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); $container->pack_start($scrolled_win); // Creates the list store if (defined("GObject::TYPE_STRING")) { $model = new GtkListStore(GObject::TYPE_LONG, GObject::TYPE_LONG, GObject::TYPE_STRING); } else { $model = new GtkListStore(Gtk::TYPE_LONG, Gtk::TYPE_LONG, Gtk::TYPE_STRING); } $field_header = array('Row', 'Col', 'Value'); $field_justification = array(0.5, 0.5, 0.0); // Creates the view to display the list store $view = new GtkTreeView($model); $scrolled_win->add($view); // Creates the columns for ($col=0; $col<count($field_header); ++$col) { $cell_renderer = new GtkCellRendererText(); $cell_renderer->set_property("xalign", $field_justification[$col]); $column = new GtkTreeViewColumn($field_header[$col], $cell_renderer, 'text', $col); $column->set_alignment($field_justification[$col]); $column->set_sort_column_id($col); // set the header font and color $label = new GtkLabel($field_header[$col]); $label->modify_font(new PangoFontDescription("Arial Bold")); $label->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000FF")); $column->set_widget($label); $label->show(); // setup self-defined function to display alternate row color $column->set_cell_data_func($cell_renderer, "format_col", $col); $view->append_column($column); } // pupulates the data for ($row=0; $row<count($data); ++$row) { $values = array(); for ($col=0; $col<count($data[$row]); ++$col) { $values[] = $data[$row][$col]; } $model->append($values); } return $view; } // display alternate row color function format_col($column, $cell, $model, $iter, $col_num) { $path = $model->get_path($iter); // get the current path $row_num = $path[0]; // get the row number if ($col_num==3) { $amt = $model->get_value($iter, 3); $cell->set_property('text', '$'.number_format($amt,2)); } $row_color = ($row_num%2==1) ? '#dddddd' : '#ffffff'; $cell->set_property('cell-background', $row_color); } // process drag function on_drag($widget, $context, $data, $info, $time, $row, $col, $value) { $drag_content = array($row, $col, $value); // note 3 $data->set_text(serialize($drag_content)); // note 3 } // process drop function on_drop($widget, $context, $x, $y, $data, $info, $time, $images) { // note 6 // append the dragged item to the destination view $dragged_content = unserialize($data->data); // note 4 $model = $widget->get_model(); $model->append($dragged_content); // note 5 } ?> |
Output
As shown above.
Explanation
This example make use of the code from the article How to drag and drop between 2 GtkTreeViews - Part 1 - left to right?
This table on the left was direct from the article How to display a 2D array in table - Part 5?
What's new here:
- Set up drag on the left side (the table). Note that we have to setup drag on the eventbox containing the label.
- Set up drop on the right side (the tree view).
- Set the data to be dragged.
- Grab the dragged data.
- Show the dragged data in the treeview. Note that we didn't do any check for duplicate data here to keep the code easier to read and understand.
Related Links
- How to drag and drop between a table and a list - Part 2 - in both directions?
- How to drag and drop between 2 GtkTreeViews - Part 1 - left to right?
- How to drag and drop between 2 GtkTreeViews - Part 2 - in both directions?
- How to select thumbnail images with drag and drop using GtkIconView - Part 1 - left to right?
- How to select thumbnail images with drag and drop using GtkIconView - Part 2 - in both directions?
- How to display a 2D array in table - Part 5?
Read more...