| 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 dwt.custom.CTabItem; |
|---|
| 14 |
|
|---|
| 15 |
import dwt.dwthelper.utils; |
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
import dwt.DWT; |
|---|
| 20 |
import dwt.DWTException; |
|---|
| 21 |
import dwt.graphics.Color; |
|---|
| 22 |
import dwt.graphics.Font; |
|---|
| 23 |
import dwt.graphics.GC; |
|---|
| 24 |
import dwt.graphics.Image; |
|---|
| 25 |
import dwt.graphics.Point; |
|---|
| 26 |
import dwt.graphics.RGB; |
|---|
| 27 |
import dwt.graphics.Rectangle; |
|---|
| 28 |
import dwt.graphics.TextLayout; |
|---|
| 29 |
import dwt.widgets.Control; |
|---|
| 30 |
import dwt.widgets.Display; |
|---|
| 31 |
import dwt.widgets.Item; |
|---|
| 32 |
import dwt.widgets.Widget; |
|---|
| 33 |
import dwt.custom.CTabFolder; |
|---|
| 34 |
|
|---|
| 35 |
/** |
|---|
| 36 |
* Instances of this class represent a selectable user interface object |
|---|
| 37 |
* that represent a page in a notebook widget. |
|---|
| 38 |
* |
|---|
| 39 |
* <dl> |
|---|
| 40 |
* <dt><b>Styles:</b></dt> |
|---|
| 41 |
* <dd>DWT.CLOSE</dd> |
|---|
| 42 |
* <dt><b>Events:</b></dt> |
|---|
| 43 |
* <dd>(none)</dd> |
|---|
| 44 |
* </dl> |
|---|
| 45 |
* <p> |
|---|
| 46 |
* IMPORTANT: This class is <em>not</em> intended to be subclassed. |
|---|
| 47 |
* </p> |
|---|
| 48 |
* |
|---|
| 49 |
* @see <a href="http://www.eclipse.org/swt/snippets/#ctabfolder">CTabFolder, CTabItem snippets</a> |
|---|
| 50 |
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> |
|---|
| 51 |
*/ |
|---|
| 52 |
public class CTabItem : Item { |
|---|
| 53 |
CTabFolder parent; |
|---|
| 54 |
int x,y,width,height = 0; |
|---|
| 55 |
Control control; // the tab page |
|---|
| 56 |
|
|---|
| 57 |
String toolTipText; |
|---|
| 58 |
String shortenedText; |
|---|
| 59 |
int shortenedTextWidth; |
|---|
| 60 |
|
|---|
| 61 |
// Appearance |
|---|
| 62 |
Font font; |
|---|
| 63 |
Image disabledImage; |
|---|
| 64 |
|
|---|
| 65 |
Rectangle closeRect; |
|---|
| 66 |
int closeImageState = CTabFolder.NONE; |
|---|
| 67 |
bool showClose = false; |
|---|
| 68 |
bool showing = false; |
|---|
| 69 |
|
|---|
| 70 |
// internal constants |
|---|
| 71 |
static final int TOP_MARGIN = 2; |
|---|
| 72 |
static final int BOTTOM_MARGIN = 2; |
|---|
| 73 |
static final int LEFT_MARGIN = 4; |
|---|
| 74 |
static final int RIGHT_MARGIN = 4; |
|---|
| 75 |
static final int INTERNAL_SPACING = 4; |
|---|
| 76 |
static final int FLAGS = DWT.DRAW_TRANSPARENT | DWT.DRAW_MNEMONIC; |
|---|
| 77 |
static final String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026" |
|---|
| 78 |
|
|---|
| 79 |
/** |
|---|
| 80 |
* Constructs a new instance of this class given its parent |
|---|
| 81 |
* (which must be a <code>CTabFolder</code>) and a style value |
|---|
| 82 |
* describing its behavior and appearance. The item is added |
|---|
| 83 |
* to the end of the items maintained by its parent. |
|---|
| 84 |
* <p> |
|---|
| 85 |
* The style value is either one of the style constants defined in |
|---|
| 86 |
* class <code>DWT</code> which is applicable to instances of this |
|---|
| 87 |
* class, or must be built by <em>bitwise OR</em>'ing together |
|---|
| 88 |
* (that is, using the <code>int</code> "|" operator) two or more |
|---|
| 89 |
* of those <code>DWT</code> style constants. The class description |
|---|
| 90 |
* lists the style constants that are applicable to the class. |
|---|
| 91 |
* Style bits are also inherited from superclasses. |
|---|
| 92 |
* </p> |
|---|
| 93 |
* |
|---|
| 94 |
* @param parent a CTabFolder which will be the parent of the new instance (cannot be null) |
|---|
| 95 |
* @param style the style of control to construct |
|---|
| 96 |
* |
|---|
| 97 |
* @exception IllegalArgumentException <ul> |
|---|
| 98 |
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
|---|
| 99 |
* </ul> |
|---|
| 100 |
* @exception DWTException <ul> |
|---|
| 101 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> |
|---|
| 102 |
* </ul> |
|---|
| 103 |
* |
|---|
| 104 |
* @see DWT |
|---|
| 105 |
* @see Widget#getStyle() |
|---|
| 106 |
*/ |
|---|
| 107 |
public this (CTabFolder parent, int style) { |
|---|
| 108 |
this(parent, style, parent.getItemCount()); |
|---|
| 109 |
} |
|---|
| 110 |
/** |
|---|
| 111 |
* Constructs a new instance of this class given its parent |
|---|
| 112 |
* (which must be a <code>CTabFolder</code>), a style value |
|---|
| 113 |
* describing its behavior and appearance, and the index |
|---|
| 114 |
* at which to place it in the items maintained by its parent. |
|---|
| 115 |
* <p> |
|---|
| 116 |
* The style value is either one of the style constants defined in |
|---|
| 117 |
* class <code>DWT</code> which is applicable to instances of this |
|---|
| 118 |
* class, or must be built by <em>bitwise OR</em>'ing together |
|---|
| 119 |
* (that is, using the <code>int</code> "|" operator) two or more |
|---|
| 120 |
* of those <code>DWT</code> style constants. The class description |
|---|
| 121 |
* lists the style constants that are applicable to the class. |
|---|
| 122 |
* Style bits are also inherited from superclasses. |
|---|
| 123 |
* </p> |
|---|
| 124 |
* |
|---|
| 125 |
* @param parent a CTabFolder which will be the parent of the new instance (cannot be null) |
|---|
| 126 |
* @param style the style of control to construct |
|---|
| 127 |
* @param index the zero-relative index to store the receiver in its parent |
|---|
| 128 |
* |
|---|
| 129 |
* @exception IllegalArgumentException <ul> |
|---|
| 130 |
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
|---|
| 131 |
* <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li> |
|---|
| 132 |
* </ul> |
|---|
| 133 |
* @exception DWTException <ul> |
|---|
| 134 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> |
|---|
| 135 |
* </ul> |
|---|
| 136 |
* |
|---|
| 137 |
* @see DWT |
|---|
| 138 |
* @see Widget#getStyle() |
|---|
| 139 |
*/ |
|---|
| 140 |
public this (CTabFolder parent, int style, int index) { |
|---|
| 141 |
closeRect = new Rectangle(0, 0, 0, 0); |
|---|
| 142 |
super (parent, style); |
|---|
| 143 |
showClose = (style & DWT.CLOSE) !is 0; |
|---|
| 144 |
parent.createItem (this, index); |
|---|
| 145 |
} |
|---|
| 146 |
|
|---|
| 147 |
/* |
|---|
| 148 |
* Return whether to use ellipses or just truncate labels |
|---|
| 149 |
*/ |
|---|
| 150 |
bool useEllipses() { |
|---|
| 151 |
return parent.simple; |
|---|
| 152 |
} |
|---|
| 153 |
|
|---|
| 154 |
String shortenText(GC gc, String text, int width) { |
|---|
| 155 |
return useEllipses() |
|---|
| 156 |
? shortenText(gc, text, width, ELLIPSIS) |
|---|
| 157 |
: shortenText(gc, text, width, ""); //$NON-NLS-1$ |
|---|
| 158 |
} |
|---|
| 159 |
|
|---|
| 160 |
String shortenText(GC gc, String text, int width, String ellipses) { |
|---|
| 161 |
if (gc.textExtent(text, FLAGS).x <= width) return text; |
|---|
| 162 |
int ellipseWidth = gc.textExtent(ellipses, FLAGS).x; |
|---|
| 163 |
int length = text.length; |
|---|
| 164 |
TextLayout layout = new TextLayout(getDisplay()); |
|---|
| 165 |
layout.setText(text); |
|---|
| 166 |
int end = layout.getPreviousOffset(length, DWT.MOVEMENT_CLUSTER); |
|---|
| 167 |
while (end > 0) { |
|---|
| 168 |
text = text[ 0 .. end ]; |
|---|
| 169 |
int l = gc.textExtent(text, FLAGS).x; |
|---|
| 170 |
if (l + ellipseWidth <= width) { |
|---|
| 171 |
break; |
|---|
| 172 |
} |
|---|
| 173 |
end = layout.getPreviousOffset(end, DWT.MOVEMENT_CLUSTER); |
|---|
| 174 |
} |
|---|
| 175 |
layout.dispose(); |
|---|
| 176 |
return end is 0 ? text.substring(0, 1) : text ~ ellipses; |
|---|
| 177 |
} |
|---|
| 178 |
|
|---|
| 179 |
public override void dispose() { |
|---|
| 180 |
if (isDisposed ()) return; |
|---|
| 181 |
//if (!isValidThread ()) error (DWT.ERROR_THREAD_INVALID_ACCESS); |
|---|
| 182 |
parent.destroyItem(this); |
|---|
| 183 |
super.dispose(); |
|---|
| 184 |
parent = null; |
|---|
| 185 |
control = null; |
|---|
| 186 |
toolTipText = null; |
|---|
| 187 |
shortenedText = null; |
|---|
| 188 |
font = null; |
|---|
| 189 |
} |
|---|
| 190 |
void drawClose(GC gc) { |
|---|
| 191 |
if (closeRect.width is 0 || closeRect.height is 0) return; |
|---|
| 192 |
Display display = getDisplay(); |
|---|
| 193 |
|
|---|
| 194 |
// draw X 9x9 |
|---|
| 195 |
int indent = Math.max(1, (CTabFolder.BUTTON_SIZE-9)/2); |
|---|
| 196 |
int x = closeRect.x + indent; |
|---|
| 197 |
int y = closeRect.y + indent; |
|---|
| 198 |
y += parent.onBottom ? -1 : 1; |
|---|
| 199 |
|
|---|
| 200 |
Color closeBorder = display.getSystemColor(CTabFolder.BUTTON_BORDER); |
|---|
| 201 |
switch (closeImageState) { |
|---|
| 202 |
case CTabFolder.NORMAL: { |
|---|
| 203 |
int[] shape = [x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y, |
|---|
| 204 |
x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9, |
|---|
| 205 |
x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9, |
|---|
| 206 |
x,y+7, x+2,y+5, x+2,y+4, x,y+2]; |
|---|
| 207 |
gc.setBackground(display.getSystemColor(CTabFolder.BUTTON_FILL)); |
|---|
| 208 |
gc.fillPolygon(shape); |
|---|
| 209 |
gc.setForeground(closeBorder); |
|---|
| 210 |
gc.drawPolygon(shape); |
|---|
| 211 |
break; |
|---|
| 212 |
} |
|---|
| 213 |
case CTabFolder.HOT: { |
|---|
| 214 |
int[] shape = [x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y, |
|---|
| 215 |
x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9, |
|---|
| 216 |
x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9, |
|---|
| 217 |
x,y+7, x+2,y+5, x+2,y+4, x,y+2]; |
|---|
| 218 |
Color fill = new Color(display, CTabFolder.CLOSE_FILL); |
|---|
| 219 |
gc.setBackground(fill); |
|---|
| 220 |
gc.fillPolygon(shape); |
|---|
| 221 |
fill.dispose(); |
|---|
| 222 |
gc.setForeground(closeBorder); |
|---|
| 223 |
gc.drawPolygon(shape); |
|---|
| 224 |
break; |
|---|
| 225 |
} |
|---|
| 226 |
case CTabFolder.SELECTED: { |
|---|
| 227 |
int[] shape = [x+1,y+1, x+3,y+1, x+5,y+3, x+6,y+3, x+8,y+1, x+10,y+1, |
|---|
| 228 |
x+10,y+3, x+8,y+5, x+8,y+6, x+10,y+8, x+10,y+10, |
|---|
| 229 |
x+8,y+10, x+6,y+8, x+5,y+8, x+3,y+10, x+1,y+10, |
|---|
| 230 |
x+1,y+8, x+3,y+6, x+3,y+5, x+1,y+3]; |
|---|
| 231 |
Color fill = new Color(display, CTabFolder.CLOSE_FILL); |
|---|
| 232 |
gc.setBackground(fill); |
|---|
| 233 |
gc.fillPolygon(shape); |
|---|
| 234 |
fill.dispose(); |
|---|
| 235 |
gc.setForeground(closeBorder); |
|---|
| 236 |
gc.drawPolygon(shape); |
|---|
| 237 |
break; |
|---|
| 238 |
} |
|---|
| 239 |
case CTabFolder.NONE: { |
|---|
| 240 |
int[] shape = [x,y, x+10,y, x+10,y+10, x,y+10]; |
|---|
| 241 |
if (parent.gradientColors !is null && !parent.gradientVertical) { |
|---|
| 242 |
parent.drawBackground(gc, shape, false); |
|---|
| 243 |
} else { |
|---|
| 244 |
Color defaultBackground = parent.getBackground(); |
|---|
| 245 |
Image image = parent.bgImage; |
|---|
| 246 |
Color[] colors = parent.gradientColors; |
|---|
| 247 |
int[] percents = parent.gradientPercents; |
|---|
| 248 |
bool vertical = parent.gradientVertical; |
|---|
| 249 |
parent.drawBackground(gc, shape, x, y, 10, 10, defaultBackground, image, colors, percents, vertical); |
|---|
| 250 |
} |
|---|
| 251 |
break; |
|---|
| 252 |
} |
|---|
| 253 |
default: |
|---|
| 254 |
} |
|---|
| 255 |
} |
|---|
| 256 |
void drawSelected(GC gc ) { |
|---|
| 257 |
Point size = parent.getSize(); |
|---|
| 258 |
int rightEdge = Math.min (x + width, parent.getRightItemEdge()); |
|---|
| 259 |
|
|---|
| 260 |
// Draw selection border across all tabs |
|---|
| 261 |
int xx = parent.borderLeft; |
|---|
| 262 |
int yy = parent.onBottom ? size.y - parent.borderBottom - parent.tabHeight - parent.highlight_header : parent.borderTop + parent.tabHeight + 1; |
|---|
| 263 |
int ww = size.x - parent.borderLeft - parent.borderRight; |
|---|
| 264 |
int hh = parent.highlight_header - 1; |
|---|
| 265 |
int[] shape = [xx,yy, xx+ww,yy, xx+ww,yy+hh, xx,yy+hh]; |
|---|
| 266 |
if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) { |
|---|
| 267 |
parent.drawBackground(gc, shape, true); |
|---|
| 268 |
} else { |
|---|
| 269 |
gc.setBackground(parent.selectionBackground); |
|---|
| 270 |
gc.fillRectangle(xx, yy, ww, hh); |
|---|
| 271 |
} |
|---|
| 272 |
|
|---|
| 273 |
if (parent.single) { |
|---|
| 274 |
if (!showing) return; |
|---|
| 275 |
} else { |
|---|
| 276 |
// if selected tab scrolled out of view or partially out of view |
|---|
| 277 |
// just draw bottom line |
|---|
| 278 |
if (!showing){ |
|---|
| 279 |
int x1 = Math.max(0, parent.borderLeft - 1); |
|---|
| 280 |
int y1 = (parent.onBottom) ? y - 1 : y + height; |
|---|
| 281 |
int x2 = size.x - parent.borderRight; |
|---|
| 282 |
gc.setForeground(CTabFolder.borderColor); |
|---|
| 283 |
gc.drawLine(x1, y1, x2, y1); |
|---|
| 284 |
return; |
|---|
| 285 |
} |
|---|
| 286 |
|
|---|
| 287 |
// draw selected tab background and outline |
|---|
| 288 |
shape = null; |
|---|
| 289 |
if (this.parent.onBottom) { |
|---|
| 290 |
int[] left = parent.simple ? CTabFolder.SIMPLE_BOTTOM_LEFT_CORNER : CTabFolder.BOTTOM_LEFT_CORNER; |
|---|
| 291 |
int[] right = parent.simple ? CTabFolder.SIMPLE_BOTTOM_RIGHT_CORNER : parent.curve; |
|---|
| 292 |
if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { |
|---|
| 293 |
left = [x, y+height]; |
|---|
| 294 |
} |
|---|
| 295 |
shape = new int[left.length+right.length+8]; |
|---|
| 296 |
int index = 0; |
|---|
| 297 |
shape[index++] = x; // first point repeated here because below we reuse shape to draw outline |
|---|
| 298 |
shape[index++] = y - 1; |
|---|
| 299 |
shape[index++] = x; |
|---|
| 300 |
shape[index++] = y - 1; |
|---|
| 301 |
for (int i = 0; i < left.length/2; i++) { |
|---|
| 302 |
shape[index++] = x + left[2*i]; |
|---|
| 303 |
shape[index++] = y + height + left[2*i+1] - 1; |
|---|
| 304 |
} |
|---|
| 305 |
for (int i = 0; i < right.length/2; i++) { |
|---|
| 306 |
shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i]; |
|---|
| 307 |
shape[index++] = parent.simple ? y + height + right[2*i+1] - 1 : y + right[2*i+1] - 2; |
|---|
| 308 |
} |
|---|
| 309 |
shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; |
|---|
| 310 |
shape[index++] = y - 1; |
|---|
| 311 |
shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; |
|---|
| 312 |
shape[index++] = y - 1; |
|---|
| 313 |
} else { |
|---|
| 314 |
int[] left = parent.simple ? CTabFolder.SIMPLE_TOP_LEFT_CORNER : CTabFolder.TOP_LEFT_CORNER; |
|---|
| 315 |
int[] right = parent.simple ? CTabFolder.SIMPLE_TOP_RIGHT_CORNER : parent.curve; |
|---|
| 316 |
if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { |
|---|
| 317 |
left = [x, y]; |
|---|
| 318 |
} |
|---|
| 319 |
shape = new int[left.length+right.length+8]; |
|---|
| 320 |
int index = 0; |
|---|
| 321 |
shape[index++] = x; // first point repeated here because below we reuse shape to draw outline |
|---|
| 322 |
shape[index++] = y + height + 1; |
|---|
| 323 |
shape[index++] = x; |
|---|
| 324 |
shape[index++] = y + height + 1; |
|---|
| 325 |
for (int i = 0; i < left.length/2; i++) { |
|---|
| 326 |
shape[index++] = x + left[2*i]; |
|---|
| 327 |
shape[index++] = y + left[2*i+1]; |
|---|
| 328 |
} |
|---|
| 329 |
for (int i = 0; i < right.length/2; i++) { |
|---|
| 330 |
shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i]; |
|---|
| 331 |
shape[index++] = y + right[2*i+1]; |
|---|
| 332 |
} |
|---|
| 333 |
shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; |
|---|
| 334 |
shape[index++] = y + height + 1; |
|---|
| 335 |
shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; |
|---|
| 336 |
shape[index++] = y + height + 1; |
|---|
| 337 |
} |
|---|
| 338 |
|
|---|
| 339 |
Rectangle clipping = gc.getClipping(); |
|---|
| 340 |
Rectangle bounds = getBounds(); |
|---|
| 341 |
bounds.height += 1; |
|---|
| 342 |
if (parent.onBottom) bounds.y -= 1; |
|---|
| 343 |
bool tabInPaint = clipping.intersects(bounds); |
|---|
| 344 |
|
|---|
| 345 |
if (tabInPaint) { |
|---|
| 346 |
// fill in tab background |
|---|
| 347 |
if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) { |
|---|
| 348 |
parent.drawBackground(gc, shape, true); |
|---|
| 349 |
} else { |
|---|
| 350 |
Color defaultBackground = parent.selectionBackground; |
|---|
| 351 |
Image image = parent.selectionBgImage; |
|---|
| 352 |
Color[] colors = parent.selectionGradientColors; |
|---|
| 353 |
int[] percents = parent.selectionGradientPercents; |
|---|
| 354 |
bool vertical = parent.selectionGradientVertical; |
|---|
| 355 |
xx = x; |
|---|
| 356 |
yy = parent.onBottom ? y -1 : y + 1; |
|---|
| 357 |
ww = width; |
|---|
| 358 |
hh = height; |
|---|
| 359 |
if (!parent.single && !parent.simple) ww += parent.curveWidth - parent.curveIndent; |
|---|
| 360 |
parent.drawBackground(gc, shape, xx, yy, ww, hh, defaultBackground, image, colors, percents, vertical); |
|---|
| 361 |
} |
|---|
| 362 |
} |
|---|
| 363 |
|
|---|
| 364 |
//Highlight MUST be drawn before the outline so that outline can cover it in the right spots (start of swoop) |
|---|
| 365 |
//otherwise the curve looks jagged |
|---|
| 366 |
drawHighlight(gc, rightEdge); |
|---|
| 367 |
|
|---|
| 368 |
// draw outline |
|---|
| 369 |
shape[0] = Math.max(0, parent.borderLeft - 1); |
|---|
| 370 |
if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { |
|---|
| 371 |
shape[1] = parent.onBottom ? y + height - 1 : y; |
|---|
| 372 |
shape[5] = shape[3] = shape[1]; |
|---|
| 373 |
} |
|---|
| 374 |
shape[shape.length - 2] = size.x - parent.borderRight + 1; |
|---|
| 375 |
for (int i = 0; i < shape.length/2; i++) { |
|---|
| 376 |
if (shape[2*i + 1] is y + height + 1) shape[2*i + 1] -= 1; |
|---|
| 377 |
} |
|---|
| 378 |
RGB inside = parent.selectionBackground.getRGB(); |
|---|
| 379 |
if (parent.selectionBgImage !is null || |
|---|
| 380 |
(parent.selectionGradientColors !is null && parent.selectionGradientColors.length > 1)) { |
|---|
| 381 |
inside = null; |
|---|
| 382 |
} |
|---|
| 383 |
RGB outside = parent.getBackground().getRGB(); |
|---|
| 384 |
if (parent.bgImage !is null || |
|---|
| 385 |
(parent.gradientColors !is null && parent.gradientColors.length > 1)) { |
|---|
| 386 |
outside = null; |
|---|
| 387 |
} |
|---|
| 388 |
parent.antialias(shape, CTabFolder.borderColor.getRGB(), inside, outside, gc); |
|---|
| 389 |
gc.setForeground(CTabFolder.borderColor); |
|---|
| 390 |
gc.drawPolyline(shape); |
|---|
| 391 |
|
|---|
| 392 |
if (!tabInPaint) return; |
|---|
| 393 |
} |
|---|
| 394 |
|
|---|
| 395 |
// draw Image |
|---|
| 396 |
int xDraw = x + LEFT_MARGIN; |
|---|
| 397 |
if (parent.single && (parent.showClose || showClose)) xDraw += CTabFolder.BUTTON_SIZE; |
|---|
| 398 |
Image image = getImage(); |
|---|
| 399 |
if (image !is null) { |
|---|
| 400 |
Rectangle imageBounds = image.getBounds(); |
|---|
| 401 |
// only draw image if it won't overlap with close button |
|---|
| 402 |
int maxImageWidth = rightEdge - xDraw - RIGHT_MARGIN; |
|---|
| 403 |
if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING; |
|---|
| 404 |
if (imageBounds.width < maxImageWidth) { |
|---|
| 405 |
int imageX = xDraw; |
|---|
| 406 |
int imageY = y + (height - imageBounds.height) / 2; |
|---|
| 407 |
imageY += parent.onBottom ? -1 : 1; |
|---|
| 408 |
gc.drawImage(image, imageX, imageY); |
|---|
| 409 |
xDraw += imageBounds.width + INTERNAL_SPACING; |
|---|
| 410 |
} |
|---|
| 411 |
} |
|---|
| 412 |
|
|---|
| 413 |
// draw Text |
|---|
| 414 |
int textWidth = rightEdge - xDraw - RIGHT_MARGIN; |
|---|
| 415 |
if (!parent.single && closeRect.width > 0) textWidth -= closeRect.width + INTERNAL_SPACING; |
|---|
| 416 |
if (textWidth > 0) { |
|---|
| 417 |
Font gcFont = gc.getFont(); |
|---|
| 418 |
gc.setFont(font is null ? parent.getFont() : font); |
|---|
| 419 |
|
|---|
| 420 |
if (shortenedText is null || shortenedTextWidth !is textWidth) { |
|---|
| 421 |
shortenedText = shortenText(gc, getText(), textWidth); |
|---|
| 422 |
shortenedTextWidth = textWidth; |
|---|
| 423 |
} |
|---|
| 424 |
Point extent = gc.textExtent(shortenedText, FLAGS); |
|---|
| 425 |
int textY = y + (height - extent.y) / 2; |
|---|
| 426 |
textY += parent.onBottom ? -1 : 1; |
|---|
| 427 |
|
|---|
| 428 |
gc.setForeground(parent.selectionForeground); |
|---|
| 429 |
gc.drawText(shortenedText, xDraw, textY, FLAGS); |
|---|
| 430 |
gc.setFont(gcFont); |
|---|
| 431 |
|
|---|
| 432 |
// draw a Focus rectangle |
|---|
| 433 |
if (parent.isFocusControl()) { |
|---|
| 434 |
Display display = getDisplay(); |
|---|
| 435 |
if (parent.simple || parent.single) { |
|---|
| 436 |
gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); |
|---|
| 437 |
gc.setForeground(display.getSystemC |
|---|