001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: /*
014: * Copyright (C) 2004 by Friederich Kupzog Elektronik & Software
015: * All rights reserved. This program and the accompanying materials
016: * are made available under the terms of the Eclipse Public License v1.0
017: * which accompanies this distribution, and is available at
018: * http://www.eclipse.org/legal/epl-v10.html
019:
020: Author: Friederich Kupzog
021: fkmk@kupzog.de
022: www.kupzog.de/fkmk
023: */
024: package org.pentaho.designstudio.widgets.flowtable;
025:
026: import org.eclipse.swt.SWT;
027: import org.eclipse.swt.graphics.Color;
028: import org.eclipse.swt.graphics.GC;
029: import org.eclipse.swt.graphics.Image;
030: import org.eclipse.swt.graphics.Point;
031: import org.eclipse.swt.graphics.RGB;
032: import org.eclipse.swt.graphics.Rectangle;
033: import org.eclipse.swt.widgets.Display;
034: import org.pentaho.actionsequence.dom.ActionControlStatement;
035: import org.pentaho.actionsequence.dom.ActionIfStatement;
036: import org.pentaho.actionsequence.dom.ActionLoop;
037: import org.pentaho.actionsequence.dom.actions.ActionDefinition;
038: import org.pentaho.designstudio.messages.Messages;
039:
040: import de.kupzog.ktable.KTableCellRenderer;
041: import de.kupzog.ktable.KTableModel;
042:
043: /**
044: * @author Friederich Kupzog
045: */
046: public class ActionsRenderer implements KTableCellRenderer {
047:
048: protected Display display;
049: int dropRow = -1;
050:
051: public static final int ARROW_LINE_WIDTH = 3;
052: public static final int ARROW_TURN_LENGTH = 10;
053: public static final int BOX_LINE_WIDTH = 1;
054: public static final int LEFT_MARGIN = 20;
055: public static final int RIGHT_MARGIN = 1;
056: public static final int TOP_MARGIN = 1;
057: public static final int BOTTOM_MARGIN = 1;
058: public static final int INNER_BORDER_WIDTH = 2;
059: public static final int INDENT_WIDTH = 30;
060: public static final int BOX_SPACING = 25;
061: public static final int BOX_WIDTH = 180;
062: public static final int ARROW_HEIGHT = 7;
063: public static final int ARROW_WIDTH = 4;
064: public static final int SHADOW_WIDTH = 2;
065: public static final RGB BOX_COLOR_RGB = new RGB(245, 245, 255);
066:
067: static final Color TEXT_COLOR = Display.getDefault()
068: .getSystemColor(SWT.COLOR_BLACK);
069: static final Color BACK_COLOR = Display.getDefault()
070: .getSystemColor(SWT.COLOR_WHITE);
071: static final Color BORDER_COLOR = Display.getDefault()
072: .getSystemColor(SWT.COLOR_DARK_GRAY);
073: static final Color SHADOW_COLOR = Display.getDefault()
074: .getSystemColor(SWT.COLOR_DARK_GRAY);
075: static final Color SELECTED_COLOR = Display.getDefault()
076: .getSystemColor(SWT.COLOR_GRAY);
077: static final Color BOX_FILL_COLOR = new Color(Display.getDefault(),
078: BOX_COLOR_RGB);
079: static final Color ARROW_COLOR = TEXT_COLOR;
080:
081: public ActionsRenderer() {
082: display = Display.getCurrent();
083: }
084:
085: public ActionsRenderer(FlowViewer flowViewer) {
086:
087: }
088:
089: public int getOptimalWidth(GC gc, int col, int row, Object content,
090: boolean fixed, KTableModel model) {
091: return BOX_WIDTH;
092: }
093:
094: /**
095: * Returns the height of the cell including the image height
096: *
097: * @param imageHeight
098: * @return
099: */
100: public int getRowHeight(int imageHeight, FlowContent flowContent) {
101: String text = flowContent.getDescription();
102: GC gc = new GC(display);
103: Point p = gc.textExtent(text);
104: gc.dispose();
105:
106: int height = Math.max(imageHeight, p.y + 3)
107: + INNER_BORDER_WIDTH * 2 + TOP_MARGIN + BOTTOM_MARGIN
108: + BOX_LINE_WIDTH * 2;
109:
110: if (!(flowContent instanceof OutputContent)) {
111: height += BOX_SPACING;
112: } else {
113: height += SHADOW_WIDTH;
114: }
115:
116: return (height);
117: }
118:
119: private void drawRectangle(GC gc, Rectangle imageBounds,
120: boolean focus, FlowContent flowContent, boolean roundCorners) {
121: String description = flowContent.getDescription();
122: Image image = flowContent.getImage();
123:
124: gc.setBackground(SHADOW_COLOR);
125: gc.setForeground(SHADOW_COLOR);
126: if (roundCorners) {
127: gc.fillRoundRectangle(imageBounds.x + SHADOW_WIDTH,
128: imageBounds.y + SHADOW_WIDTH, imageBounds.width,
129: imageBounds.height, 20, 20);
130: } else {
131: gc.fillRectangle(imageBounds.x + SHADOW_WIDTH,
132: imageBounds.y + SHADOW_WIDTH, imageBounds.width,
133: imageBounds.height);
134: }
135:
136: if (focus) {
137: if (roundCorners) {
138: gc.setBackground(BOX_FILL_COLOR);
139: gc.fillRoundRectangle(imageBounds.x, imageBounds.y,
140: imageBounds.width, imageBounds.height, 20, 20);
141:
142: gc.setBackground(SELECTED_COLOR);
143: gc.fillRoundRectangle(imageBounds.x + 20,
144: imageBounds.y, imageBounds.width - 20,
145: imageBounds.height, 20, 20);
146:
147: gc.setForeground(BOX_FILL_COLOR);
148: gc.setBackground(SELECTED_COLOR);
149: gc.fillGradientRectangle(imageBounds.x + 20,
150: imageBounds.y, imageBounds.width - 40,
151: imageBounds.height, false);
152:
153: } else {
154: gc.setForeground(BOX_FILL_COLOR);
155: gc.setBackground(SELECTED_COLOR);
156: gc.fillGradientRectangle(imageBounds.x, imageBounds.y,
157: imageBounds.width, imageBounds.height, false);
158: }
159: } else {
160: gc.setBackground(BOX_FILL_COLOR);
161: if (roundCorners) {
162: gc.fillRoundRectangle(imageBounds.x, imageBounds.y,
163: imageBounds.width, imageBounds.height, 20, 20);
164: } else {
165: gc.fillRectangle(imageBounds);
166: }
167: }
168: gc.setBackground(BACK_COLOR);
169: gc.setForeground(BORDER_COLOR);
170:
171: if (roundCorners) {
172: gc.drawRoundRectangle(imageBounds.x, imageBounds.y,
173: imageBounds.width, imageBounds.height, 20, 20);
174: } else {
175: gc.drawRectangle(imageBounds);
176: }
177:
178: int imgW;
179: int imgH;
180: if (image != null) {
181: imgW = image.getBounds().width;
182: imgH = image.getBounds().height;
183: gc.drawImage(image, imageBounds.x + INNER_BORDER_WIDTH,
184: imageBounds.y + (imageBounds.height - imgH) / 2);
185: } else {
186: imgW = -INNER_BORDER_WIDTH; // if no image, subtract out the border
187: // between the image and text
188: imgH = 0;
189: }
190:
191: Rectangle textBox = new Rectangle(imageBounds.x + imgW + 2
192: * INNER_BORDER_WIDTH, imageBounds.y
193: + INNER_BORDER_WIDTH, imageBounds.width - imgW
194: - INNER_BORDER_WIDTH * 3 - BOX_LINE_WIDTH,
195: imageBounds.height - INNER_BORDER_WIDTH * 2
196: - BOX_LINE_WIDTH + 2);
197:
198: flowContent.textBox = textBox;
199:
200: Rectangle oldClip = gc.getClipping();
201: gc.setForeground(TEXT_COLOR);
202: gc.setClipping(textBox);
203: gc.drawText(description, textBox.x, textBox.y, true);
204: gc.setClipping(oldClip);
205: }
206:
207: private void drawTerminator(GC gc, Rectangle cellBounds,
208: boolean focus, TerminatorContent terminatorContent,
209: boolean isDropTarget) {
210: int indentLevel = terminatorContent.indentLevel;
211:
212: Rectangle imageBounds = new Rectangle(cellBounds.x
213: + LEFT_MARGIN + indentLevel * INDENT_WIDTH + 1,
214: cellBounds.y + TOP_MARGIN, Math.min(BOX_WIDTH,
215: cellBounds.width - LEFT_MARGIN - RIGHT_MARGIN
216: - BOX_LINE_WIDTH), cellBounds.height
217: - TOP_MARGIN - BOTTOM_MARGIN - BOX_SPACING
218: - BOX_LINE_WIDTH);
219:
220: drawRectangle(gc, imageBounds, focus, terminatorContent, true);
221:
222: gc.setForeground(ARROW_COLOR);
223: gc.setBackground(ARROW_COLOR);
224: gc.setLineWidth(ARROW_LINE_WIDTH);
225: int arrowStartX = imageBounds.x + imageBounds.width / 2;
226: int arrowStartY = imageBounds.y + imageBounds.height;
227: int arrowEndY = cellBounds.y + cellBounds.height;
228:
229: gc.setForeground(ARROW_COLOR);
230: gc.setBackground(ARROW_COLOR);
231: ActionControlStatement controlStatement = (ActionControlStatement) terminatorContent
232: .getData();
233:
234: gc.drawLine(arrowStartX, arrowStartY, arrowStartX, arrowEndY
235: - ARROW_HEIGHT);
236: gc
237: .fillPolygon(new int[] { arrowStartX - ARROW_WIDTH,
238: arrowEndY - ARROW_HEIGHT, arrowStartX,
239: arrowEndY, arrowStartX + ARROW_WIDTH + 1,
240: arrowEndY - ARROW_HEIGHT });
241: if (controlStatement instanceof ActionLoop) {
242: gc
243: .drawPolyline(new int[] { imageBounds.x,
244: imageBounds.y + imageBounds.height / 2,
245: imageBounds.x - ARROW_TURN_LENGTH,
246: imageBounds.y + imageBounds.height / 2,
247: imageBounds.x - ARROW_TURN_LENGTH,
248: cellBounds.y - 1 });
249: } else {
250: gc
251: .drawPolyline(new int[] {
252: imageBounds.x - ARROW_HEIGHT,
253: imageBounds.y + imageBounds.height / 2,
254: imageBounds.x - ARROW_TURN_LENGTH,
255: imageBounds.y + imageBounds.height / 2,
256: imageBounds.x - ARROW_TURN_LENGTH,
257: cellBounds.y - 1 });
258: gc.fillPolygon(new int[] {
259: imageBounds.x,
260: imageBounds.y + imageBounds.height / 2,
261: imageBounds.x - ARROW_HEIGHT,
262: imageBounds.y + imageBounds.height / 2
263: - ARROW_WIDTH,
264: imageBounds.x - ARROW_HEIGHT,
265: imageBounds.y + imageBounds.height / 2
266: + ARROW_WIDTH });
267: }
268:
269: if (isDropTarget) {
270: gc.drawLine(arrowStartX - 10, arrowStartY
271: + (arrowEndY - arrowStartY) / 2, arrowStartX + 10,
272: arrowStartY + (arrowEndY - arrowStartY) / 2);
273: }
274:
275: int xPos = cellBounds.x + LEFT_MARGIN - ARROW_TURN_LENGTH + 1;
276: if (controlStatement instanceof ActionControlStatement) {
277: gc.setForeground(ARROW_COLOR);
278: for (int i = 0; i < indentLevel; i++) {
279: gc.drawLine(xPos, cellBounds.y - 3, xPos, arrowEndY);
280: xPos += INDENT_WIDTH;
281: }
282: }
283: }
284:
285: private void drawActionDefinition(GC gc, Rectangle cellBounds,
286: boolean focus, ActionContent actionContent,
287: boolean isDropTarget) {
288: int indentLevel = actionContent.indentLevel;
289: ActionDefinition actionDefinition = (ActionDefinition) actionContent
290: .getData();
291:
292: Rectangle imageBounds = new Rectangle(cellBounds.x
293: + LEFT_MARGIN + indentLevel * INDENT_WIDTH + 1,
294: cellBounds.y + TOP_MARGIN, Math.min(BOX_WIDTH,
295: cellBounds.width - LEFT_MARGIN - RIGHT_MARGIN
296: - BOX_LINE_WIDTH), cellBounds.height
297: - TOP_MARGIN - BOTTOM_MARGIN - BOX_SPACING
298: - BOX_LINE_WIDTH);
299:
300: drawRectangle(gc, imageBounds, focus, actionContent, false);
301:
302: gc.setForeground(ARROW_COLOR);
303: gc.setBackground(ARROW_COLOR);
304: gc.setLineWidth(ARROW_LINE_WIDTH);
305: int arrowStartX = imageBounds.x + imageBounds.width / 2;
306: int arrowStartY = imageBounds.y + imageBounds.height;
307: int arrowEndY = cellBounds.y + cellBounds.height;
308:
309: gc.drawLine(arrowStartX, arrowStartY, arrowStartX, arrowEndY
310: - ARROW_HEIGHT);
311: gc
312: .fillPolygon(new int[] { arrowStartX - ARROW_WIDTH,
313: arrowEndY - ARROW_HEIGHT, arrowStartX,
314: arrowEndY, arrowStartX + ARROW_WIDTH + 1,
315: arrowEndY - ARROW_HEIGHT });
316:
317: if (isDropTarget) {
318: gc.drawLine(arrowStartX - 10, arrowStartY
319: + (arrowEndY - arrowStartY) / 2, arrowStartX + 10,
320: arrowStartY + (arrowEndY - arrowStartY) / 2);
321: }
322:
323: int xPos = cellBounds.x + LEFT_MARGIN - ARROW_TURN_LENGTH + 1;
324: ActionControlStatement parent = actionDefinition.getParent();
325: if (parent instanceof ActionControlStatement) {
326: gc.setForeground(ARROW_COLOR);
327: for (int i = 0; i < indentLevel; i++) {
328: gc.drawLine(xPos, cellBounds.y - 3, xPos, arrowEndY);
329: xPos += INDENT_WIDTH;
330: }
331: }
332: }
333:
334: private void drawIf(GC gc, Rectangle cellBounds, boolean focus,
335: IfContent ifContent, boolean isDropTarget) {
336: int indentLevel = ifContent.indentLevel;
337: String description = ifContent.getDescription();
338: ActionIfStatement actionIfStatement = (ActionIfStatement) ifContent
339: .getData();
340:
341: Rectangle imageBounds = new Rectangle(cellBounds.x
342: + LEFT_MARGIN + indentLevel * INDENT_WIDTH + 1,
343: cellBounds.y + TOP_MARGIN, Math.min(BOX_WIDTH,
344: cellBounds.width - LEFT_MARGIN - RIGHT_MARGIN
345: - BOX_LINE_WIDTH), cellBounds.height
346: - TOP_MARGIN - BOTTOM_MARGIN - BOX_SPACING
347: - BOX_LINE_WIDTH);
348:
349: gc.setBackground(SHADOW_COLOR);
350: gc.setForeground(SHADOW_COLOR);
351: gc.fillPolygon(new int[] {
352: imageBounds.x + SHADOW_WIDTH,
353: imageBounds.y + imageBounds.height / 2 + SHADOW_WIDTH,
354: imageBounds.x + SHADOW_WIDTH + imageBounds.height / 2,
355: imageBounds.y + SHADOW_WIDTH,
356: imageBounds.x + SHADOW_WIDTH + imageBounds.width
357: - imageBounds.height / 2,
358: imageBounds.y + SHADOW_WIDTH,
359: imageBounds.x + SHADOW_WIDTH + imageBounds.width,
360: imageBounds.y + imageBounds.height / 2 + SHADOW_WIDTH,
361: imageBounds.x + SHADOW_WIDTH + imageBounds.width
362: - imageBounds.height / 2,
363: imageBounds.y + imageBounds.height + SHADOW_WIDTH,
364: imageBounds.x + SHADOW_WIDTH + imageBounds.height / 2,
365: imageBounds.y + imageBounds.height + SHADOW_WIDTH });
366:
367: if (focus) {
368: gc.setBackground(BOX_FILL_COLOR);
369: gc.fillPolygon(new int[] { imageBounds.x,
370: imageBounds.y + imageBounds.height / 2,
371: imageBounds.x + imageBounds.height / 2 + 1,
372: imageBounds.y,
373: imageBounds.x + imageBounds.height / 2 + 1,
374: imageBounds.y + imageBounds.height });
375:
376: gc.setBackground(SELECTED_COLOR);
377: gc.fillPolygon(new int[] {
378: imageBounds.x + imageBounds.width
379: - imageBounds.height / 2 - 1,
380: imageBounds.y,
381: imageBounds.x + imageBounds.width,
382: imageBounds.y + imageBounds.height / 2,
383: imageBounds.x + imageBounds.width
384: - imageBounds.height / 2 - 1,
385: imageBounds.y + imageBounds.height });
386:
387: gc.setForeground(BOX_FILL_COLOR);
388: gc.setBackground(SELECTED_COLOR);
389: gc.fillGradientRectangle(imageBounds.x + imageBounds.height
390: / 2, imageBounds.y, imageBounds.width
391: - imageBounds.height, imageBounds.height, false);
392: } else {
393: gc.setBackground(BOX_FILL_COLOR);
394: gc.fillPolygon(new int[] {
395: imageBounds.x,
396: imageBounds.y + imageBounds.height / 2,
397: imageBounds.x + imageBounds.height / 2,
398: imageBounds.y,
399: imageBounds.x + imageBounds.width
400: - imageBounds.height / 2,
401: imageBounds.y,
402: imageBounds.x + imageBounds.width,
403: imageBounds.y + imageBounds.height / 2,
404: imageBounds.x + imageBounds.width
405: - imageBounds.height / 2,
406: imageBounds.y + imageBounds.height,
407: imageBounds.x + imageBounds.height / 2,
408: imageBounds.y + imageBounds.height });
409: }
410: gc.setBackground(BACK_COLOR);
411: gc.setForeground(BORDER_COLOR);
412:
413: gc.drawPolygon(new int[] {
414: imageBounds.x,
415: imageBounds.y + imageBounds.height / 2,
416: imageBounds.x + imageBounds.height / 2,
417: imageBounds.y,
418: imageBounds.x + imageBounds.width - imageBounds.height
419: / 2,
420: imageBounds.y,
421: imageBounds.x + imageBounds.width,
422: imageBounds.y + imageBounds.height / 2,
423: imageBounds.x + imageBounds.width - imageBounds.height
424: / 2, imageBounds.y + imageBounds.height,
425: imageBounds.x + imageBounds.height / 2,
426: imageBounds.y + imageBounds.height });
427:
428: Rectangle textBox = new Rectangle(imageBounds.x
429: + imageBounds.height / 2, imageBounds.y
430: + INNER_BORDER_WIDTH, imageBounds.width
431: - imageBounds.height, imageBounds.height
432: - INNER_BORDER_WIDTH * 2);
433:
434: ifContent.textBox = textBox;
435:
436: Rectangle oldClip = gc.getClipping();
437: gc.setForeground(TEXT_COLOR);
438: gc.setClipping(textBox);
439: gc.drawText(description, textBox.x, textBox.y, true);
440: gc.setClipping(oldClip);
441:
442: gc.setForeground(ARROW_COLOR);
443: gc.setBackground(ARROW_COLOR);
444: gc.setLineWidth(ARROW_LINE_WIDTH);
445: int arrowStartX = imageBounds.x + imageBounds.width / 2;
446: int arrowStartY = imageBounds.y + imageBounds.height;
447: int arrowEndY = cellBounds.y + cellBounds.height;
448:
449: gc.setBackground(BACK_COLOR);
450: gc.setForeground(TEXT_COLOR);
451: gc
452: .drawText(
453: Messages
454: .getString("ActionsRenderer.TRUE_LABEL"), arrowStartX + 5, arrowStartY + 5); //$NON-NLS-1$
455: gc
456: .drawText(
457: Messages
458: .getString("ActionsRenderer.FALSE_LABEL"), imageBounds.x - ARROW_TURN_LENGTH + 5, arrowStartY + 5); //$NON-NLS-1$
459: gc.setForeground(ARROW_COLOR);
460: gc.setBackground(ARROW_COLOR);
461: gc.drawLine(arrowStartX, arrowStartY, arrowStartX, arrowEndY
462: - ARROW_HEIGHT);
463: gc
464: .fillPolygon(new int[] { arrowStartX - ARROW_WIDTH,
465: arrowEndY - ARROW_HEIGHT, arrowStartX,
466: arrowEndY, arrowStartX + ARROW_WIDTH + 1,
467: arrowEndY - ARROW_HEIGHT });
468:
469: gc.drawPolyline(new int[] { imageBounds.x,
470: imageBounds.y + imageBounds.height / 2,
471: imageBounds.x - ARROW_TURN_LENGTH,
472: imageBounds.y + imageBounds.height / 2,
473: imageBounds.x - ARROW_TURN_LENGTH,
474: cellBounds.y + cellBounds.height });
475:
476: if (isDropTarget) {
477: gc.drawLine(arrowStartX - 10, arrowStartY
478: + (arrowEndY - arrowStartY) / 2, arrowStartX + 10,
479: arrowStartY + (arrowEndY - arrowStartY) / 2);
480: }
481:
482: int xPos = cellBounds.x + LEFT_MARGIN - ARROW_TURN_LENGTH + 1;
483: if (actionIfStatement.getParent() instanceof ActionControlStatement) {
484: gc.setForeground(ARROW_COLOR);
485: for (int i = 0; i < indentLevel; i++) {
486: gc.drawLine(xPos, cellBounds.y - 3, xPos, arrowEndY);
487: xPos += INDENT_WIDTH;
488: }
489: }
490: }
491:
492: private void drawLoop(GC gc, Rectangle cellBounds, boolean focus,
493: LoopContent loopContent, boolean isDropTarget) {
494:
495: int indentLevel = loopContent.indentLevel;
496: ActionLoop actionLoop = (ActionLoop) loopContent.getData();
497:
498: Rectangle imageBounds = new Rectangle(cellBounds.x
499: + LEFT_MARGIN + indentLevel * INDENT_WIDTH + 1,
500: cellBounds.y + TOP_MARGIN, Math.min(BOX_WIDTH,
501: cellBounds.width - LEFT_MARGIN - RIGHT_MARGIN
502: - BOX_LINE_WIDTH), cellBounds.height
503: - TOP_MARGIN - BOTTOM_MARGIN - BOX_SPACING
504: - BOX_LINE_WIDTH);
505: drawRectangle(gc, imageBounds, focus, loopContent, true);
506:
507: gc.setForeground(ARROW_COLOR);
508: gc.setBackground(ARROW_COLOR);
509: gc.setLineWidth(ARROW_LINE_WIDTH);
510: int arrowStartX = imageBounds.x + imageBounds.width / 2;
511: int arrowStartY = imageBounds.y + imageBounds.height;
512: int arrowEndY = cellBounds.y + cellBounds.height;
513:
514: gc.drawLine(arrowStartX, arrowStartY, arrowStartX, arrowEndY
515: - ARROW_HEIGHT);
516: gc
517: .fillPolygon(new int[] { arrowStartX - ARROW_WIDTH,
518: arrowEndY - ARROW_HEIGHT, arrowStartX,
519: arrowEndY, arrowStartX + ARROW_WIDTH + 1,
520: arrowEndY - ARROW_HEIGHT });
521:
522: gc.drawPolyline(new int[] { imageBounds.x - ARROW_HEIGHT,
523: imageBounds.y + imageBounds.height / 2,
524: imageBounds.x - ARROW_TURN_LENGTH,
525: imageBounds.y + imageBounds.height / 2,
526: imageBounds.x - ARROW_TURN_LENGTH,
527: cellBounds.y + cellBounds.height });
528: gc.fillPolygon(new int[] { imageBounds.x,
529: imageBounds.y + imageBounds.height / 2,
530: imageBounds.x - ARROW_HEIGHT,
531: imageBounds.y + imageBounds.height / 2 - ARROW_WIDTH,
532: imageBounds.x - ARROW_HEIGHT,
533: imageBounds.y + imageBounds.height / 2 + ARROW_WIDTH });
534:
535: if (isDropTarget) {
536: gc.drawLine(arrowStartX - 10, arrowStartY
537: + (arrowEndY - arrowStartY) / 2, arrowStartX + 10,
538: arrowStartY + (arrowEndY - arrowStartY) / 2);
539: }
540:
541: int xPos = cellBounds.x + LEFT_MARGIN - ARROW_TURN_LENGTH + 1;
542: if (actionLoop.getParent() instanceof ActionControlStatement) {
543: gc.setForeground(ARROW_COLOR);
544: for (int i = 0; i < indentLevel; ++i) {
545: gc.drawLine(xPos, cellBounds.y - 3, xPos, arrowEndY);
546: xPos += INDENT_WIDTH;
547: }
548: }
549: }
550:
551: private void drawInput(GC gc, Rectangle cellBounds, boolean focus,
552: InputContent inputContent, boolean isDropTarget) {
553: Rectangle imageBounds = new Rectangle(cellBounds.x
554: + LEFT_MARGIN + 1, cellBounds.y + TOP_MARGIN, Math.min(
555: BOX_WIDTH, cellBounds.width - LEFT_MARGIN
556: - RIGHT_MARGIN - BOX_LINE_WIDTH),
557: cellBounds.height - TOP_MARGIN - BOTTOM_MARGIN
558: - BOX_SPACING - BOX_LINE_WIDTH);
559:
560: drawRectangle(gc, imageBounds, focus, inputContent, false);
561:
562: gc.setForeground(ARROW_COLOR);
563: gc.setBackground(ARROW_COLOR);
564: gc.setLineWidth(ARROW_LINE_WIDTH);
565: int arrowStartX = imageBounds.x + imageBounds.width / 2;
566: int arrowStartY = imageBounds.y + imageBounds.height;
567: int arrowEndY = cellBounds.y + cellBounds.height;
568:
569: gc.drawLine(arrowStartX, arrowStartY, arrowStartX, arrowEndY
570: - ARROW_HEIGHT);
571: gc
572: .fillPolygon(new int[] { arrowStartX - ARROW_WIDTH,
573: arrowEndY - ARROW_HEIGHT, arrowStartX,
574: arrowEndY, arrowStartX + ARROW_WIDTH + 1,
575: arrowEndY - ARROW_HEIGHT });
576:
577: if (isDropTarget) {
578: gc.drawLine(arrowStartX - 10, arrowStartY
579: + (arrowEndY - arrowStartY) / 2, arrowStartX + 10,
580: arrowStartY + (arrowEndY - arrowStartY) / 2);
581: }
582:
583: }
584:
585: private void drawOutput(GC gc, Rectangle cellBounds, boolean focus,
586: OutputContent outputContent) {
587: Rectangle imageBounds = new Rectangle(cellBounds.x
588: + LEFT_MARGIN + 1, cellBounds.y + TOP_MARGIN, Math.min(
589: BOX_WIDTH, cellBounds.width - LEFT_MARGIN
590: - RIGHT_MARGIN - BOX_LINE_WIDTH),
591: cellBounds.height - TOP_MARGIN - BOTTOM_MARGIN * 2
592: - SHADOW_WIDTH - BOX_LINE_WIDTH);
593:
594: drawRectangle(gc, imageBounds, focus, outputContent, false);
595: }
596:
597: private void drawResource(GC gc, Rectangle cellBounds,
598: boolean focus, ResourceContent resourceContent,
599: boolean isDropTarget) {
600: Rectangle imageBounds = new Rectangle(cellBounds.x
601: + LEFT_MARGIN + 1, cellBounds.y + TOP_MARGIN, Math.min(
602: BOX_WIDTH, cellBounds.width - LEFT_MARGIN
603: - RIGHT_MARGIN * 2 - BOX_LINE_WIDTH),
604: cellBounds.height - TOP_MARGIN - BOTTOM_MARGIN * 2
605: - BOX_SPACING - BOX_LINE_WIDTH);
606:
607: drawRectangle(gc, imageBounds, focus, resourceContent, false);
608:
609: gc.setForeground(ARROW_COLOR);
610: gc.setBackground(ARROW_COLOR);
611: gc.setLineWidth(ARROW_LINE_WIDTH);
612: int arrowStartX = imageBounds.x + imageBounds.width / 2;
613: int arrowStartY = imageBounds.y + imageBounds.height;
614: int arrowEndY = cellBounds.y + cellBounds.height;
615:
616: gc.drawLine(arrowStartX, arrowStartY, arrowStartX, arrowEndY
617: - ARROW_HEIGHT);
618: gc
619: .fillPolygon(new int[] { arrowStartX - ARROW_WIDTH,
620: arrowEndY - ARROW_HEIGHT, arrowStartX,
621: arrowEndY, arrowStartX + ARROW_WIDTH + 1,
622: arrowEndY - ARROW_HEIGHT });
623:
624: if (isDropTarget) {
625: gc.drawLine(arrowStartX - 10, arrowStartY
626: + (arrowEndY - arrowStartY) / 2, arrowStartX + 10,
627: arrowStartY + (arrowEndY - arrowStartY) / 2);
628: }
629:
630: }
631:
632: public void drawCell(GC gc, Rectangle cellBounds, int col, int row,
633: Object content, boolean focus, boolean fixed,
634: boolean clicked, KTableModel model) {
635: FlowContent myContent = (FlowContent) content;
636:
637: gc.setAntialias(SWT.ON);
638: gc.setLineJoin(SWT.JOIN_MITER);
639: gc.setForeground(BORDER_COLOR);
640: gc.setBackground(BACK_COLOR);
641:
642: // Cheat the clipping -
643: gc.setClipping(cellBounds.x, cellBounds.y - 2,
644: cellBounds.width, cellBounds.height + 3);
645: gc.fillRectangle(cellBounds.x, cellBounds.y,
646: cellBounds.width + 1, cellBounds.height + 2);
647:
648: gc.setLineWidth(BOX_LINE_WIDTH);
649:
650: if (content instanceof IfContent) {
651: drawIf(gc, cellBounds, focus, (IfContent) content,
652: row == dropRow);
653: } else if (content instanceof LoopContent) {
654: drawLoop(gc, cellBounds, focus, (LoopContent) content,
655: row == dropRow);
656: } else if (content instanceof OutputContent) {
657: drawOutput(gc, cellBounds, focus, (OutputContent) content);
658: } else if (content instanceof InputContent) {
659: drawInput(gc, cellBounds, focus, (InputContent) content,
660: row == dropRow);
661: } else if (content instanceof ResourceContent) {
662: drawResource(gc, cellBounds, focus,
663: (ResourceContent) content, row == dropRow);
664: } else if (content instanceof TerminatorContent) {
665: drawTerminator(gc, cellBounds, focus,
666: (TerminatorContent) content, row == dropRow);
667: } else {
668: drawActionDefinition(gc, cellBounds, focus,
669: (ActionContent) myContent, row == dropRow);
670: }
671:
672: }
673:
674: public void setDropRow(int dropRow) {
675: this .dropRow = dropRow;
676: }
677:
678: public int getDropRow() {
679: return dropRow;
680: }
681: }
|