| 1 |
/******************************************************************************* |
|---|
| 2 |
* Copyright (c) 2007, 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 dwt.dnd.TreeDragSourceEffect; |
|---|
| 14 |
|
|---|
| 15 |
import dwt.DWT; |
|---|
| 16 |
import dwt.graphics.Image; |
|---|
| 17 |
import dwt.graphics.ImageData; |
|---|
| 18 |
import dwt.graphics.PaletteData; |
|---|
| 19 |
import dwt.graphics.Rectangle; |
|---|
| 20 |
import dwt.internal.win32.OS; |
|---|
| 21 |
import dwt.widgets.Display; |
|---|
| 22 |
import dwt.widgets.Tree; |
|---|
| 23 |
import dwt.widgets.TreeItem; |
|---|
| 24 |
|
|---|
| 25 |
import dwt.dnd.DragSourceEffect; |
|---|
| 26 |
import dwt.dnd.DragSourceEvent; |
|---|
| 27 |
|
|---|
| 28 |
import dwt.dwthelper.utils; |
|---|
| 29 |
|
|---|
| 30 |
/** |
|---|
| 31 |
* This class provides default implementations to display a source image |
|---|
| 32 |
* when a drag is initiated from a <code>Tree</code>. |
|---|
| 33 |
* |
|---|
| 34 |
* <p>Classes that wish to provide their own source image for a <code>Tree</code> can |
|---|
| 35 |
* extend <code>TreeDragSourceEffect</code> class and override the <code>TreeDragSourceEffect.dragStart</code> |
|---|
| 36 |
* method and set the field <code>DragSourceEvent.image</code> with their own image.</p> |
|---|
| 37 |
* |
|---|
| 38 |
* Subclasses that override any methods of this class must call the corresponding |
|---|
| 39 |
* <code>super</code> method to get the default drag under effect implementation. |
|---|
| 40 |
* |
|---|
| 41 |
* @see DragSourceEffect |
|---|
| 42 |
* @see DragSourceEvent |
|---|
| 43 |
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> |
|---|
| 44 |
* |
|---|
| 45 |
* @since 3.3 |
|---|
| 46 |
*/ |
|---|
| 47 |
public class TreeDragSourceEffect : DragSourceEffect { |
|---|
| 48 |
Image dragSourceImage = null; |
|---|
| 49 |
|
|---|
| 50 |
/** |
|---|
| 51 |
* Creates a new <code>TreeDragSourceEffect</code> to handle drag effect |
|---|
| 52 |
* from the specified <code>Tree</code>. |
|---|
| 53 |
* |
|---|
| 54 |
* @param tree the <code>Tree</code> that the user clicks on to initiate the drag |
|---|
| 55 |
*/ |
|---|
| 56 |
public this(Tree tree) { |
|---|
| 57 |
super(tree); |
|---|
| 58 |
} |
|---|
| 59 |
|
|---|
| 60 |
/** |
|---|
| 61 |
* This implementation of <code>dragFinished</code> disposes the image |
|---|
| 62 |
* that was created in <code>TreeDragSourceEffect.dragStart</code>. |
|---|
| 63 |
* |
|---|
| 64 |
* Subclasses that override this method should call <code>super.dragFinished(event)</code> |
|---|
| 65 |
* to dispose the image in the default implementation. |
|---|
| 66 |
* |
|---|
| 67 |
* @param event the information associated with the drag finished event |
|---|
| 68 |
*/ |
|---|
| 69 |
public void dragFinished(DragSourceEvent event) { |
|---|
| 70 |
if (dragSourceImage !is null) dragSourceImage.dispose(); |
|---|
| 71 |
dragSourceImage = null; |
|---|
| 72 |
} |
|---|
| 73 |
|
|---|
| 74 |
/** |
|---|
| 75 |
* This implementation of <code>dragStart</code> will create a default |
|---|
| 76 |
* image that will be used during the drag. The image should be disposed |
|---|
| 77 |
* when the drag is completed in the <code>TreeDragSourceEffect.dragFinished</code> |
|---|
| 78 |
* method. |
|---|
| 79 |
* |
|---|
| 80 |
* Subclasses that override this method should call <code>super.dragStart(event)</code> |
|---|
| 81 |
* to use the image from the default implementation. |
|---|
| 82 |
* |
|---|
| 83 |
* @param event the information associated with the drag start event |
|---|
| 84 |
*/ |
|---|
| 85 |
public void dragStart(DragSourceEvent event) { |
|---|
| 86 |
event.image = getDragSourceImage(event); |
|---|
| 87 |
} |
|---|
| 88 |
|
|---|
| 89 |
Image getDragSourceImage(DragSourceEvent event) { |
|---|
| 90 |
if (dragSourceImage !is null) dragSourceImage.dispose(); |
|---|
| 91 |
dragSourceImage = null; |
|---|
| 92 |
if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { |
|---|
| 93 |
SHDRAGIMAGE shdi; |
|---|
| 94 |
int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ("ShellGetDragImage"w.ptr); //$NON-NLS-1$ |
|---|
| 95 |
if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) { |
|---|
| 96 |
if ((control.getStyle() & DWT.MIRRORED) !is 0) { |
|---|
| 97 |
event.x += shdi.sizeDragImage.cx - shdi.ptOffset.x; |
|---|
| 98 |
} else { |
|---|
| 99 |
event.x += shdi.ptOffset.x; |
|---|
| 100 |
} |
|---|
| 101 |
event.y += shdi.ptOffset.y; |
|---|
| 102 |
auto hImage = shdi.hbmpDragImage; |
|---|
| 103 |
if (hImage !is null) { |
|---|
| 104 |
BITMAP bm; |
|---|
| 105 |
OS.GetObject (hImage, BITMAP.sizeof, &bm); |
|---|
| 106 |
int srcWidth = bm.bmWidth; |
|---|
| 107 |
int srcHeight = bm.bmHeight; |
|---|
| 108 |
|
|---|
| 109 |
/* Create resources */ |
|---|
| 110 |
auto hdc = OS.GetDC (null); |
|---|
| 111 |
auto srcHdc = OS.CreateCompatibleDC (hdc); |
|---|
| 112 |
auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage); |
|---|
| 113 |
auto memHdc = OS.CreateCompatibleDC (hdc); |
|---|
| 114 |
BITMAPINFOHEADER bmiHeader; |
|---|
| 115 |
bmiHeader.biSize = BITMAPINFOHEADER.sizeof; |
|---|
| 116 |
bmiHeader.biWidth = srcWidth; |
|---|
| 117 |
bmiHeader.biHeight = -srcHeight; |
|---|
| 118 |
bmiHeader.biPlanes = 1; |
|---|
| 119 |
bmiHeader.biBitCount = 32; |
|---|
| 120 |
bmiHeader.biCompression = OS.BI_RGB; |
|---|
| 121 |
void* pBits; |
|---|
| 122 |
auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0); |
|---|
| 123 |
if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES); |
|---|
| 124 |
auto oldMemBitmap = OS.SelectObject (memHdc, memDib); |
|---|
| 125 |
|
|---|
| 126 |
BITMAP dibBM; |
|---|
| 127 |
OS.GetObject (memDib, BITMAP.sizeof, &dibBM); |
|---|
| 128 |
int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight; |
|---|
| 129 |
|
|---|
| 130 |
/* Get the foreground pixels */ |
|---|
| 131 |
OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY); |
|---|
| 132 |
byte[] srcData = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ]; |
|---|
| 133 |
|
|---|
| 134 |
PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); |
|---|
| 135 |
ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData); |
|---|
| 136 |
if (shdi.crColorKey is -1) { |
|---|
| 137 |
byte[] alphaData = new byte[srcWidth * srcHeight]; |
|---|
| 138 |
int spinc = dibBM.bmWidthBytes - srcWidth * 4; |
|---|
| 139 |
int ap = 0, sp = 3; |
|---|
| 140 |
for (int y = 0; y < srcHeight; ++y) { |
|---|
| 141 |
for (int x = 0; x < srcWidth; ++x) { |
|---|
| 142 |
alphaData [ap++] = srcData [sp]; |
|---|
| 143 |
sp += 4; |
|---|
| 144 |
} |
|---|
| 145 |
sp += spinc; |
|---|
| 146 |
} |
|---|
| 147 |
data.alphaData = alphaData; |
|---|
| 148 |
} else { |
|---|
| 149 |
data.transparentPixel = shdi.crColorKey << 8; |
|---|
| 150 |
} |
|---|
| 151 |
dragSourceImage = new Image (control.getDisplay (), data); |
|---|
| 152 |
OS.SelectObject (memHdc, oldMemBitmap); |
|---|
| 153 |
OS.DeleteDC (memHdc); |
|---|
| 154 |
OS.DeleteObject (memDib); |
|---|
| 155 |
OS.SelectObject (srcHdc, oldSrcBitmap); |
|---|
| 156 |
OS.DeleteDC (srcHdc); |
|---|
| 157 |
OS.ReleaseDC (null, hdc); |
|---|
| 158 |
OS.DeleteObject (hImage); |
|---|
| 159 |
return dragSourceImage; |
|---|
| 160 |
} |
|---|
| 161 |
} |
|---|
| 162 |
return null; |
|---|
| 163 |
} |
|---|
| 164 |
|
|---|
| 165 |
Tree tree = cast(Tree) control; |
|---|
| 166 |
//TEMPORARY CODE |
|---|
| 167 |
if (tree.isListening (DWT.EraseItem) || tree.isListening (DWT.PaintItem)) return null; |
|---|
| 168 |
TreeItem[] selection = tree.getSelection(); |
|---|
| 169 |
if (selection.length is 0) return null; |
|---|
| 170 |
auto treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0); |
|---|
| 171 |
if (treeImageList !is 0) { |
|---|
| 172 |
int count = Math.min(selection.length, 10); |
|---|
| 173 |
Rectangle bounds = selection[0].getBounds(0); |
|---|
| 174 |
for (int i = 1; i < count; i++) { |
|---|
| 175 |
bounds = bounds.makeUnion(selection[i].getBounds(0)); |
|---|
| 176 |
} |
|---|
| 177 |
auto hDC = OS.GetDC(tree.handle); |
|---|
| 178 |
auto hDC1 = OS.CreateCompatibleDC(hDC); |
|---|
| 179 |
auto bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height); |
|---|
| 180 |
auto hOldBitmap = OS.SelectObject(hDC1, bitmap); |
|---|
| 181 |
RECT rect; |
|---|
| 182 |
rect.right = bounds.width; |
|---|
| 183 |
rect.bottom = bounds.height; |
|---|
| 184 |
auto hBrush = OS.GetStockObject(OS.WHITE_BRUSH); |
|---|
| 185 |
OS.FillRect(hDC1, &rect, hBrush); |
|---|
| 186 |
for (int i = 0; i < count; i++) { |
|---|
| 187 |
TreeItem selected = selection[i]; |
|---|
| 188 |
Rectangle cell = selected.getBounds(0); |
|---|
| 189 |
HANDLE imageList = cast(HANDLE) OS.SendMessage(tree.handle, OS.TVM_CREATEDRAGIMAGE, 0, selected.handle); |
|---|
| 190 |
OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED); |
|---|
| 191 |
OS.ImageList_Destroy(imageList); |
|---|
| 192 |
} |
|---|
| 193 |
OS.SelectObject(hDC1, hOldBitmap); |
|---|
| 194 |
OS.DeleteDC (hDC1); |
|---|
| 195 |
OS.ReleaseDC (tree.handle, hDC); |
|---|
| 196 |
Display display = tree.getDisplay(); |
|---|
| 197 |
dragSourceImage = Image.win32_new(display, DWT.BITMAP, bitmap); |
|---|
| 198 |
return dragSourceImage; |
|---|
| 199 |
} |
|---|
| 200 |
return null; |
|---|
| 201 |
} |
|---|
| 202 |
} |
|---|