1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.dnd.TableDragSourceEffect;
14 
15 import java.lang.all;
16 
17 
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.graphics.Image;
20 import org.eclipse.swt.internal.gtk.OS;
21 import org.eclipse.swt.widgets.Display;
22 import org.eclipse.swt.widgets.Table;
23 import org.eclipse.swt.dnd.DragSourceEffect;
24 import org.eclipse.swt.dnd.DragSourceEvent;
25 
26 
27 /**
28  * This class provides default implementations to display a source image
29  * when a drag is initiated from a <code>Table</code>.
30  *
31  * <p>Classes that wish to provide their own source image for a <code>Table</code> can
32  * extend the <code>TableDragSourceEffect</code> class, override the
33  * <code>TableDragSourceEffect.dragStart</code> method and set the field
34  * <code>DragSourceEvent.image</code> with their own image.</p>
35  *
36  * Subclasses that override any methods of this class must call the corresponding
37  * <code>super</code> method to get the default drag source effect implementation.
38  *
39  * @see DragSourceEffect
40  * @see DragSourceEvent
41  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
42  *
43  * @since 3.3
44  */
45 public class TableDragSourceEffect : DragSourceEffect {
46     Image dragSourceImage = null;
47 
48     /**
49      * Creates a new <code>TableDragSourceEffect</code> to handle drag effect
50      * from the specified <code>Table</code>.
51      *
52      * @param table the <code>Table</code> that the user clicks on to initiate the drag
53      */
54     public this(Table table) {
55         super(table);
56     }
57 
58     /**
59      * This implementation of <code>dragFinished</code> disposes the image
60      * that was created in <code>TableDragSourceEffect.dragStart</code>.
61      *
62      * Subclasses that override this method should call <code>super.dragFinished(event)</code>
63      * to dispose the image in the default implementation.
64      *
65      * @param event the information associated with the drag finished event
66      */
67     public override void dragFinished(DragSourceEvent event) {
68         if (dragSourceImage !is null) dragSourceImage.dispose();
69         dragSourceImage = null;
70     }
71 
72     /**
73      * This implementation of <code>dragStart</code> will create a default
74      * image that will be used during the drag. The image should be disposed
75      * when the drag is completed in the <code>TableDragSourceEffect.dragFinished</code>
76      * method.
77      *
78      * Subclasses that override this method should call <code>super.dragStart(event)</code>
79      * to use the image from the default implementation.
80      *
81      * @param event the information associated with the drag start event
82      */
83     public override void dragStart(DragSourceEvent event) {
84         event.image = getDragSourceImage(event);
85     }
86 
87     Image getDragSourceImage(DragSourceEvent event) {
88         if (dragSourceImage !is null) dragSourceImage.dispose();
89         dragSourceImage = null;
90 
91         Table table = cast(Table) control;
92         if (OS.GTK_VERSION < OS.buildVERSION (2, 2, 0)) return null;
93         //TEMPORARY CODE
94         if (table.isListening(SWT.EraseItem) || table.isListening (SWT.PaintItem)) return null;
95         /*
96         * Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
97         * in versions smaller than 2.2.4 if the model is NULL.  The fix is
98         * to give a valid pointer instead.
99         */
100         auto handle = table.handle;
101         auto selection = OS.gtk_tree_view_get_selection (handle);
102         int dummy;
103         void* model = OS.GTK_VERSION < OS.buildVERSION (2, 2, 4) ? &dummy : null;
104         auto list = OS.gtk_tree_selection_get_selected_rows (selection, &model);
105         if (list is null) return null;
106         ptrdiff_t count = Math.min(10, OS.g_list_length (list));
107 
108         Display display = table.getDisplay();
109         if (count is 1) {
110             auto path = OS.g_list_nth_data (list, 0);
111             auto pixmap = OS.gtk_tree_view_create_row_drag_icon(handle, path);
112             dragSourceImage =  Image.gtk_new(display, SWT.ICON, pixmap, null);
113         } else {
114             int width = 0, height = 0;
115             int w, h;
116             int[] yy, hh; yy.length = count; hh.length = count;
117             GdkDrawable*[] pixmaps; pixmaps.length = count;
118             GdkRectangle rect;
119             for (int i=0; i<count; i++) {
120                 auto path = OS.g_list_nth_data (list, i);
121                 OS.gtk_tree_view_get_cell_area (handle, path, null, &rect);
122                 pixmaps[i] = OS.gtk_tree_view_create_row_drag_icon(handle, path);
123                 OS.gdk_drawable_get_size(pixmaps[i], &w, &h);
124                 width = Math.max(width, w);
125                 height = rect.y + h - yy[0];
126                 yy[i] = rect.y;
127                 hh[i] = h;
128             }
129             auto source = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width, height, -1);
130             auto gcSource = OS.gdk_gc_new(source);
131             auto mask = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width, height, 1);
132             auto gcMask = OS.gdk_gc_new(mask);
133             GdkColor color;
134             color.pixel = 0;
135             OS.gdk_gc_set_foreground(gcMask, &color);
136             OS.gdk_draw_rectangle(mask, gcMask, 1, 0, 0, width, height);
137             color.pixel = 1;
138             OS.gdk_gc_set_foreground(gcMask, &color);
139             for (int i=0; i<count; i++) {
140                 OS.gdk_draw_drawable(source, gcSource, pixmaps[i], 0, 0, 0, yy[i] - yy[0], -1, -1);
141                 OS.gdk_draw_rectangle(mask, gcMask, 1, 0, yy[i] - yy[0], width, hh[i]);
142                 OS.g_object_unref(pixmaps[i]);
143             }
144             OS.g_object_unref(gcSource);
145             OS.g_object_unref(gcMask);
146             dragSourceImage  = Image.gtk_new(display, SWT.ICON, source, mask);
147         }
148         OS.g_list_free (list);
149 
150         return dragSourceImage;
151 }
152 }