4 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
7 * GiWoong Kim <giwoong.kim@samsung.com>
8 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or ( at your option ) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 package org.tizen.emulator.skin.custom;
31 import java.util.List;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.custom.ScrolledComposite;
35 import org.eclipse.swt.events.MouseEvent;
36 import org.eclipse.swt.events.MouseListener;
37 import org.eclipse.swt.events.MouseMoveListener;
38 import org.eclipse.swt.events.PaintEvent;
39 import org.eclipse.swt.events.PaintListener;
40 import org.eclipse.swt.events.ShellEvent;
41 import org.eclipse.swt.events.ShellListener;
42 import org.eclipse.swt.graphics.Color;
43 import org.eclipse.swt.graphics.Image;
44 import org.eclipse.swt.graphics.ImageData;
45 import org.eclipse.swt.graphics.Point;
46 import org.eclipse.swt.graphics.RGB;
47 import org.eclipse.swt.graphics.Rectangle;
48 import org.eclipse.swt.graphics.Region;
49 import org.eclipse.swt.layout.GridData;
50 import org.eclipse.swt.layout.GridLayout;
51 import org.eclipse.swt.widgets.Composite;
52 import org.eclipse.swt.widgets.Display;
53 import org.eclipse.swt.widgets.Shell;
54 import org.tizen.emulator.skin.EmulatorSkin;
55 import org.tizen.emulator.skin.comm.ICommunicator.KeyEventType;
56 import org.tizen.emulator.skin.comm.ICommunicator.SendCommand;
57 import org.tizen.emulator.skin.comm.sock.SocketCommunicator;
58 import org.tizen.emulator.skin.comm.sock.data.KeyEventData;
59 import org.tizen.emulator.skin.dbi.KeyMapType;
60 import org.tizen.emulator.skin.image.ImageRegistry.KeyWindowImageName;
61 import org.tizen.emulator.skin.layout.SkinPatches;
62 import org.tizen.emulator.skin.util.SwtUtil;
64 public class KeyWindow extends SkinWindow {
65 private static final String PATCH_IMAGES_PATH = "images/key-window/";
66 private static final int SHELL_MARGIN_BOTTOM = 3;
67 private static final int PAIRTAG_CIRCLE_SIZE = 8;
68 private static final int PAIRTAG_MARGIN_BOTTOM = 6;
69 private static final int BUTTON_DEFAULT_CNT = 4;
70 private static final int BUTTON_VERTICAL_SPACING = 7;
71 private static final int SCROLLBAR_HORIZONTAL_SPACING = 4;
72 private static final int SCROLLBAR_SIZE_WIDTH = 14;
74 private EmulatorSkin skin;
75 private SkinPatches frameMaker;
77 private int widthBase;
78 private int heightBase;
79 private int widthScrollbar;
80 private int cntHiddenButton;
82 private Image imageNormal; /* ImageButton image */
83 private Image imageHover; /* hovered ImageButton image */
84 private Image imagePushed; /* pushed ImageButton image */
85 private Image imageFrame; /* nine-patch image */
87 private Color colorFrame;
88 private SocketCommunicator communicator;
89 private List<KeyMapType> keyMapList;
91 private ShellListener shellListener;
92 private PaintListener shellPaintListener;
93 private MouseMoveListener shellMouseMoveListener;
94 private MouseListener shellMouseListener;
96 private boolean isGrabbedShell;
97 private Point grabPosition;
99 public KeyWindow(EmulatorSkin skin, Shell parent,
100 SocketCommunicator communicator, List<KeyMapType> keyMapList) {
101 super(parent, SWT.RIGHT | SWT.CENTER);
104 this.shell = new Shell(Display.getDefault(),
105 SWT.NO_TRIM | SWT.RESIZE | SWT.TOOL);
106 this.frameMaker = new SkinPatches(PATCH_IMAGES_PATH);
108 this.keyMapList = keyMapList; //TODO: null
109 this.communicator = communicator;
110 this.grabPosition = new Point(0, 0);
112 shell.setText(parent.getText());
113 shell.setImage(parent.getImage());
115 /* load image for HW key button */
116 imageNormal = skin.getImageRegistry().getKeyWindowImageData(
117 KeyWindowImageName.KEYBUTTON_NORMAL);
118 imageHover = skin.getImageRegistry().getKeyWindowImageData(
119 KeyWindowImageName.KEYBUTTON_HOVER);
120 imagePushed = skin.getImageRegistry().getKeyWindowImageData(
121 KeyWindowImageName.KEYBUTTON_PUSHED);
123 /* calculate the key window size */
124 widthBase = imageNormal.getImageData().width;
125 heightBase = (imageNormal.getImageData().height * BUTTON_DEFAULT_CNT) +
126 (BUTTON_VERTICAL_SPACING * (BUTTON_DEFAULT_CNT - 1));
128 widthScrollbar = SCROLLBAR_SIZE_WIDTH + SCROLLBAR_HORIZONTAL_SPACING;
129 int heightHeaderPart = (PAIRTAG_CIRCLE_SIZE + PAIRTAG_MARGIN_BOTTOM);
130 int heightTailPart = SHELL_MARGIN_BOTTOM;
132 /* make a frame image */
133 this.cntHiddenButton = 0; //keyMapList.size() - BUTTON_DEFAULT_CNT;
135 this.imageFrame = frameMaker.getPatchedImage(
136 widthBase + ((cntHiddenButton > 0) ? widthScrollbar : 0),
137 heightBase + heightHeaderPart + heightTailPart);
138 this.colorFrame = new Color(shell.getDisplay(), new RGB(38, 38, 38));
140 shell.setBackground(colorFrame);
143 trimPatchedShell(shell, imageFrame);
145 addKeyWindowListener();
147 shell.setSize(imageFrame.getImageData().width,
148 imageFrame.getImageData().height);
151 protected void createContents() {
152 GridLayout shellGridLayout = new GridLayout(1, false);
153 shellGridLayout.marginLeft = shellGridLayout.marginRight = frameMaker.getPatchWidth();
154 shellGridLayout.marginTop = frameMaker.getPatchHeight();
155 shellGridLayout.marginBottom = frameMaker.getPatchHeight() + SHELL_MARGIN_BOTTOM;
156 shellGridLayout.marginWidth = shellGridLayout.marginHeight = 0;
157 shellGridLayout.horizontalSpacing = shellGridLayout.verticalSpacing = 0;
159 shell.setLayout(shellGridLayout);
161 /* make a pair tag circle */
162 ColorTag pairTagCanvas = new ColorTag(shell, SWT.NONE, skin.getColorVM());
163 pairTagCanvas.setLayoutData(new GridData(PAIRTAG_CIRCLE_SIZE,
164 PAIRTAG_CIRCLE_SIZE + PAIRTAG_MARGIN_BOTTOM));
166 /* make a region of HW keys */
167 if (cntHiddenButton > 0) {
168 /* added custom scrollbar */
170 Image imagesScrollArrowUp[] = new Image[3];
171 Image imagesScrollArrowDown[] = new Image[3];
173 imagesScrollArrowUp[0] = skin.getImageRegistry().getKeyWindowImageData(
174 KeyWindowImageName.SCROLL_UPBUTTON_NORMAL);
175 imagesScrollArrowUp[1] = skin.getImageRegistry().getKeyWindowImageData(
176 KeyWindowImageName.SCROLL_UPBUTTON_HOVER);
177 imagesScrollArrowUp[2] = skin.getImageRegistry().getKeyWindowImageData(
178 KeyWindowImageName.SCROLL_UPBUTTON_PUSHED);
180 imagesScrollArrowDown[0] = skin.getImageRegistry().getKeyWindowImageData(
181 KeyWindowImageName.SCROLL_DOWNBUTTON_NORMAL);
182 imagesScrollArrowDown[1] = skin.getImageRegistry().getKeyWindowImageData(
183 KeyWindowImageName.SCROLL_DOWNBUTTON_HOVER);
184 imagesScrollArrowDown[2] = skin.getImageRegistry().getKeyWindowImageData(
185 KeyWindowImageName.SCROLL_DOWNBUTTON_PUSHED);
187 CustomScrolledComposite compositeScroll =
188 new CustomScrolledComposite(shell, SWT.NONE,
189 imagesScrollArrowUp, imagesScrollArrowDown,
190 skin.getImageRegistry().getKeyWindowImageData(
191 KeyWindowImageName.SCROLL_THUMB),
192 skin.getImageRegistry().getKeyWindowImageData(
193 KeyWindowImageName.SCROLL_SHAFT));
194 compositeScroll.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1));
196 Composite compositeBase = new Composite(compositeScroll, SWT.NONE);
198 createHwKeys(compositeBase);
200 Point sizeContent = compositeBase.computeSize(
201 widthBase + widthScrollbar, heightBase);
202 compositeScroll.setContent(compositeBase, sizeContent);
203 compositeScroll.setExpandHorizontal(true);
204 compositeScroll.setExpandVertical(true);
206 sizeContent.y += (imageNormal.getImageData().height * cntHiddenButton) +
207 (BUTTON_VERTICAL_SPACING * cntHiddenButton);
208 compositeScroll.setMinSize(sizeContent);
210 ScrolledComposite compositeScroll = new ScrolledComposite(shell, SWT.V_SCROLL);
211 compositeScroll.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1));
213 Composite compositeBase = new Composite(compositeScroll, SWT.NONE);
214 createHwKeys(compositeBase);
216 compositeScroll.setContent(compositeBase);
217 compositeScroll.setExpandHorizontal(true);
218 compositeScroll.setExpandVertical(true);
219 compositeScroll.setMinSize(compositeBase.computeSize(SWT.DEFAULT, SWT.DEFAULT));
223 protected void createHwKeys(Composite composite) {
224 composite.setBackground(colorFrame);
226 GridLayout compositeGridLayout = new GridLayout(1, false);
227 compositeGridLayout.marginLeft = compositeGridLayout.marginRight = 0;
228 compositeGridLayout.marginTop = compositeGridLayout.marginBottom = 0;
229 compositeGridLayout.marginWidth = compositeGridLayout.marginHeight = 0;
230 compositeGridLayout.horizontalSpacing = 0;
231 compositeGridLayout.verticalSpacing = BUTTON_VERTICAL_SPACING;
232 composite.setLayout(compositeGridLayout);
235 if (keyMapList != null && keyMapList.isEmpty() == false) {
236 for (KeyMapType keyEntry : keyMapList) {
237 CustomButton HWKeyButton = new CustomButton(composite,
238 SWT.NO_FOCUS, imageNormal, imageHover, imagePushed);
239 HWKeyButton.setText(keyEntry.getEventInfo().getKeyName());
240 HWKeyButton.setToolTipText(keyEntry.getTooltip());
241 HWKeyButton.setBackground(colorFrame);
242 HWKeyButton.setLayoutData(new GridData(imageNormal.getImageData().width,
243 imageNormal.getImageData().height));
245 final int keycode = keyEntry.getEventInfo().getKeyCode();
246 HWKeyButton.addMouseListener(new MouseListener() {
248 public void mouseDown(MouseEvent e) {
249 KeyEventData keyEventData = new KeyEventData(
250 KeyEventType.PRESSED.value(), keycode, 0, 0);
251 communicator.sendToQEMU(SendCommand.SEND_HARD_KEY_EVENT, keyEventData);
255 public void mouseUp(MouseEvent e) {
256 KeyEventData keyEventData = new KeyEventData(
257 KeyEventType.RELEASED.value(), keycode, 0, 0);
258 communicator.sendToQEMU(SendCommand.SEND_HARD_KEY_EVENT, keyEventData);
262 public void mouseDoubleClick(MouseEvent e) {
270 public static void trimPatchedShell(Shell shell, Image image) {
274 ImageData imageData = image.getImageData();
276 int width = imageData.width;
277 int height = imageData.height;
279 Region region = new Region();
280 region.add(new Rectangle(0, 0, width, height));
282 int r = shell.getDisplay().getSystemColor(SWT.COLOR_MAGENTA).getRed();
283 int g = shell.getDisplay().getSystemColor(SWT.COLOR_MAGENTA).getGreen();
284 int b = shell.getDisplay().getSystemColor(SWT.COLOR_MAGENTA).getBlue();
287 if (SwtUtil.isWindowsPlatform()) {
288 colorKey = r << 24 | g << 16 | b << 8;
290 colorKey = r << 16 | g << 8 | b;
293 for (int i = 0; i < width; i++) {
294 for (int j = 0; j < height; j++) {
295 int colorPixel = imageData.getPixel(i, j);
296 if (colorPixel == colorKey /* magenta */) {
297 region.subtract(i, j, 1, 1);
302 shell.setRegion(region);
305 private void addKeyWindowListener() {
306 shellPaintListener = new PaintListener() {
308 public void paintControl(final PaintEvent e) {
309 if (imageFrame != null) {
310 e.gc.drawImage(imageFrame, 0, 0);
315 shell.addPaintListener(shellPaintListener);
317 shellListener = new ShellListener() {
319 public void shellClosed(ShellEvent event) {
320 logger.info("Key Window is closed");
322 if (skin.pairTag != null) {
323 skin.pairTag.setVisible(false);
325 skin.keyWindow = null;
327 if (null != shellPaintListener) {
328 shell.removePaintListener(shellPaintListener);
331 if (null != shellListener) {
332 shell.removeShellListener(shellListener);
335 if (null != shellMouseMoveListener) {
336 shell.removeMouseMoveListener(shellMouseMoveListener);
339 if (null != shellMouseListener) {
340 shell.removeMouseListener(shellMouseListener);
343 colorFrame.dispose();
345 frameMaker.freePatches();
349 public void shellActivated(ShellEvent event) {
350 logger.info("activate");
352 if (SwtUtil.isMacPlatform() == true) {
353 parent.moveAbove(shell);
355 shell.getDisplay().asyncExec(new Runnable() {
365 public void shellDeactivated(ShellEvent event) {
366 logger.info("deactivate");
372 public void shellIconified(ShellEvent event) {
377 public void shellDeiconified(ShellEvent event) {
378 logger.info("deiconified");
380 shell.getDisplay().asyncExec(new Runnable() {
383 if (parent.getMinimized() == true) {
384 parent.setMinimized(false);
391 shell.addShellListener(shellListener);
393 shellMouseMoveListener = new MouseMoveListener() {
395 public void mouseMove(MouseEvent e) {
396 if (isGrabbedShell == true && e.button == 0/* left button */) {
397 if (getDockPosition() != SWT.NONE) {
398 dock(SWT.NONE, false, false);
399 shell.moveAbove(parent);
403 Point previousLocation = shell.getLocation();
404 int x = previousLocation.x + (e.x - grabPosition.x);
405 int y = previousLocation.y + (e.y - grabPosition.y);
407 shell.setLocation(x, y);
413 shell.addMouseMoveListener(shellMouseMoveListener);
415 shellMouseListener = new MouseListener() {
417 public void mouseUp(MouseEvent e) {
418 if (e.button == 1) { /* left button */
419 isGrabbedShell = false;
420 grabPosition.x = grabPosition.y = 0;
422 /* Let me check whether the key window was landed
423 * on docking area. */
424 Rectangle parentBounds = parent.getBounds();
425 Rectangle childBounds = shell.getBounds();
427 int heightOneThird = parentBounds.height / 3;
430 Rectangle attachBounds1 = new Rectangle(
431 (parentBounds.x + parentBounds.width) - 5,
432 parentBounds.y + heightOneThird,
435 Rectangle attachBounds2 = new Rectangle(
436 (parentBounds.x + parentBounds.width) - 5,
440 Rectangle attachBounds3 = new Rectangle(
441 (parentBounds.x + parentBounds.width) - 5,
442 parentBounds.y + (heightOneThird * 2),
445 if (childBounds.intersects(attachBounds1) == true) {
446 dock(SWT.RIGHT | SWT.CENTER, false, true);
447 } else if (childBounds.intersects(attachBounds2) == true) {
448 dock(SWT.RIGHT | SWT.TOP, false, true);
449 } else if (childBounds.intersects(attachBounds3) == true) {
450 dock(SWT.RIGHT | SWT.BOTTOM, false, true);
452 dock(SWT.NONE, false, true);
458 public void mouseDown(MouseEvent e) {
459 if (1 == e.button) { /* left button */
460 isGrabbedShell = true;
461 grabPosition.x = e.x;
462 grabPosition.y = e.y;
467 public void mouseDoubleClick(MouseEvent e) {
472 shell.addMouseListener(shellMouseListener);