private Dimension getContainerDimensions(Graphics g, steps.array.bucket.Container c) { int spacingWidth = (int) g.getFontMetrics(g.getFont()).getStringBounds(CONTAINER_VALUE_SPACING, g).getHeight(); int totalWidth = spacingWidth; int totalHeight = 0; for (int i = 0; i < c.theValues.length; i++) { totalHeight = (int) g.getFontMetrics(g.getFont()).getStringBounds("" + c.theValues[0], g).getHeight() * 2; totalWidth += (int) g.getFontMetrics(g.getFont()).getStringBounds("" + c.theValues[i], g).getWidth(); totalWidth += spacingWidth; } return new Dimension(totalWidth, totalHeight); }
/** * Draws the specified string. * * @param g graphics reference * @param s text * @param x x coordinate * @param y y coordinate * @param w width * @param fs font size */ public static void chopString( final Graphics g, final byte[] s, final int x, final int y, final int w, final int fs) { if (w < 12) return; final int[] cw = fontWidths(g.getFont()); int j = s.length; try { int l = 0; int fw = 0; for (int k = 0; k < j; k += l) { final int ww = width(g, cw, cp(s, k)); if (fw + ww >= w - 4) { j = Math.max(1, k - l); if (k > 1) fw -= width(g, cw, cp(s, k - 1)); g.drawString("..", x + fw, y + fs); break; } fw += ww; l = cl(s, k); } } catch (final Exception ex) { Util.debug(ex); } g.drawString(string(s, 0, j), x, y + fs); }
/** * Returns the width of the specified text. Cached font widths are used to speed up calculation. * * @param g graphics reference * @param s string to be evaluated * @return string width */ public static int width(final Graphics g, final byte[] s) { final int[] cw = fontWidths(g.getFont()); final int l = s.length; int fw = 0; try { // ignore faulty character sets for (int k = 0; k < l; k += cl(s, k)) fw += width(g, cw, cp(s, k)); } catch (final Exception ex) { Util.debug(ex); } return fw; }
private void drawContainer(steps.array.bucket.Container c, Graphics g, int x, int y) { // calculate the size of all the printed values Dimension dims = getContainerDimensions(g, c); int totalWidth = dims.width, totalHeight = dims.height; String allValues = CONTAINER_VALUE_SPACING; for (int i = 0; i < c.theValues.length; i++) { allValues += c.theValues[i] + CONTAINER_VALUE_SPACING; } int textWidth = (int) g.getFontMetrics(g.getFont()).getStringBounds("" + allValues, g).getWidth(); // draw a rectangle to fit them all g.drawRoundRect(x, y, totalWidth, totalHeight, ARC_RADIUS, ARC_RADIUS); // print the values in it g.drawString(allValues, x + (totalWidth - textWidth) / 2, y + 3 * totalHeight / 4); }
public void centerText(String s1, String s2, Graphics g, Color c, int x, int y, int w, int h) { // locs[0].centerText(s1, s2, this.getGraphics(), // Color.white, 400,0,200,50); // g.setXORMode(unselected_color); // centerText("pic" + im, null, g, Color.black, x, y, w, h); Font f = g.getFont(); FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(f); int ascent = fm.getAscent(); int height = fm.getHeight(); int width1 = 0, width2 = 0, x0 = 0, x1 = 0, y0 = 0, y1 = 0; width1 = fm.stringWidth(s1); if (s2 != null) width2 = fm.stringWidth(s2); x0 = x + (w - width1) / 2; x0 = x + (w - width2) / 2; if (s2 == null) y0 = y + (h - height) / 2 + ascent; else { y0 = y + (h - (int) (height * 2.2)) / 2 + ascent; y1 = y0 + (int) (height * 1.2); } g.setColor(c); g.drawString(s1, x0, y0); if (s2 != null) g.drawString(s2, x1, y1); }
/** The method to call when the thread starts */ public void run() { boolean draw = true; FontMetrics fm; Rectangle r; int sw = 0; int sa = 0; int x = 0; int y = 0; setPriority(Thread.MIN_PRIORITY); while (true) { if (newmessage != null && draw) { message = newmessage; newmessage = null; } if (lg == null) { lg = g2d.getGraphics(); if (lg != null) lg = lg.create(); } if (lg != null) { if (f != null) lg.setFont(f); fm = lg.getFontMetrics(lg.getFont()); sw = fm.stringWidth(message); sa = fm.getAscent(); } else { draw = false; } if (draw) { lg.setColor(foreground); r = g2d.bounds(); x = r.x + (r.width - sw) / 2; y = r.y + (r.height + sa) / 2; lg.drawString(message, x, y); g2d.repaint(); try { sleep(visible); } catch (Exception e) { } } else { if (lg != null) { lg.setColor(g2d.getBackground()); lg.drawString(message, x, y); g2d.repaint(); } try { sleep(invisible); } catch (Exception e) { } } draw = !draw; } }
public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; RenderingHints rh = g2d.getRenderingHints(); rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHints(rh); // Background. D = this.getSize(); g.setColor(backgroundColor); g.fillRect(0, 0, D.width, D.height); Graphics2D g2 = (Graphics2D) g; g2.setStroke(lineStroke); // Axes, bounding box. g.setColor(Color.gray); g.drawLine(inset, D.height - inset, D.width - inset, D.height - inset); g.drawLine(D.width - inset, inset, D.width - inset, D.height - inset); g.drawLine(inset, inset, inset, D.height - inset); g.drawLine(inset, inset, D.width - inset, inset); double xDelta = (maxX - minX) / numIntervals; // X-ticks and labels. for (int i = 1; i <= numIntervals; i++) { double xTickd = i * xDelta; int xTick = (int) (xTickd / (maxX - minX) * (D.width - 2 * inset)); g.drawLine(inset + xTick, D.height - inset - 5, inset + xTick, D.height - inset + 5); double x = minX + i * xDelta; g.drawString(df.format(x), xTick + inset - 5, D.height - inset + 20); } // Y-ticks double yDelta = (maxY - minY) / numIntervals; for (int i = 0; i < numIntervals; i++) { int yTick = (i + 1) * (int) ((D.height - 2 * inset) / (double) numIntervals); g.drawLine(inset - 5, D.height - yTick - inset, inset + 5, D.height - yTick - inset); double y = minY + (i + 1) * yDelta; g.drawString(df.format(y), 1, D.height - yTick - inset); } // Zoom+move Font savedFont = g.getFont(); g.setFont(plusFont); g.drawString("+", D.width - 25, 20); g.setFont(minusFont); g.drawString("-", D.width - 25, 50); drawArrow(g2d, D.width - 70, 20, D.width - 70, 0, 1.0f, lineStroke); // Up drawArrow(g2d, D.width - 70, 30, D.width - 70, 50, 1.0f, lineStroke); // Down drawArrow(g2d, D.width - 65, 25, D.width - 45, 25, 1.0f, lineStroke); // Right drawArrow(g2d, D.width - 75, 25, D.width - 95, 25, 1.0f, lineStroke); // Left g.setFont(savedFont); // See if standard axes are in the middle. g.setColor(Color.gray); if ((minX < 0) && (maxX > 0) && (drawMiddleAxes)) { // Draw y-axis int x = (int) ((0 - minX) / (maxX - minX) * (D.width - 2 * inset)); g.drawLine(inset + x, D.height - inset, inset + x, inset); } if ((minY < 0) && (maxY > 0) && (drawMiddleAxes)) { // Draw x-axis int y = (int) ((0 - minY) / (maxY - minY) * (D.height - 2.0 * inset)); g.drawLine(inset, D.height - y - inset, D.width - inset, D.height - y - inset); } // Draw the objects. drawObjects(g, points, lines, ovals, rectangles, images, labels, eqnLines); if (animationMode) { drawObjects(g, animPoints, animLines, animOvals, animRectangles, null, labels, eqnLines); // No images in animation mode. } drawScribbles(g); }
/** * parse the text. When the text is parsed the width, height, leading are all calculated. The text * will only be truly parsed if the graphics context has changed or the text has changed or the * font has changed. Otherwise nothing is done when this method is called. * * @param g Graphics context. */ public void parseText(Graphics g) { FontMetrics fm; TextState current = new TextState(); char ch; Stack state = new Stack(); int w = 0; if (lg != g) parse = true; lg = g; if (!parse) return; parse = false; width = 0; leading = 0; ascent = 0; descent = 0; height = 0; maxAscent = 0; maxDescent = 0; if (text == null || g == null) return; list.removeAllElements(); if (font == null) current.f = g.getFont(); else current.f = font; state.push(current); list.addElement(current); fm = g.getFontMetrics(current.f); for (int i = 0; i < text.length(); i++) { ch = text.charAt(i); switch (ch) { case '$': i++; if (i < text.length()) current.s.append(text.charAt(i)); break; /* ** Push the current state onto the state stack ** and start a new storage string */ case '{': w = current.getWidth(g); if (!current.isEmpty()) { current = current.copyState(); list.addElement(current); } state.push(current); current.x += w; break; /* ** Pop the state off the state stack and set the current ** state to the top of the state stack */ case '}': w = current.x + current.getWidth(g); state.pop(); current = ((TextState) state.peek()).copyState(); list.addElement(current); current.x = w; break; case '^': w = current.getWidth(g); if (!current.isEmpty()) { current = current.copyState(); list.addElement(current); } current.f = getScriptFont(current.f); current.x += w; current.y -= (int) ((double) (current.getAscent(g)) * sup_offset + 0.5); break; case '_': w = current.getWidth(g); if (!current.isEmpty()) { current = current.copyState(); list.addElement(current); } current.f = getScriptFont(current.f); current.x += w; current.y += (int) ((double) (current.getDescent(g)) * sub_offset + 0.5); break; default: current.s.append(ch); break; } } for (int i = 0; i < list.size(); i++) { current = ((TextState) (list.elementAt(i))); if (!current.isEmpty()) { width += current.getWidth(g); ascent = Math.max(ascent, Math.abs(current.y) + current.getAscent(g)); descent = Math.max(descent, Math.abs(current.y) + current.getDescent(g)); leading = Math.max(leading, current.getLeading(g)); maxDescent = Math.max(maxDescent, Math.abs(current.y) + current.getMaxDescent(g)); maxAscent = Math.max(maxAscent, Math.abs(current.y) + current.getMaxAscent(g)); } } height = ascent + descent + leading; return; }
@Override public void paintComponent(Graphics g) { super.paintComponent(g); int width = getWidth() - rightMargin - leftMargin - 10; int height = getHeight() - topMargin - bottomMargin; if (width <= 0 || height <= 0) { // not enough room to paint anything return; } Color oldColor = g.getColor(); Font oldFont = g.getFont(); Color fg = getForeground(); Color bg = getBackground(); boolean bgIsLight = (bg.getRed() > 200 && bg.getGreen() > 200 && bg.getBlue() > 200); ((Graphics2D) g) .setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (smallFont == null) { smallFont = oldFont.deriveFont(9.0F); } r.x = leftMargin - 5; r.y = topMargin - 8; r.width = getWidth() - leftMargin - rightMargin; r.height = getHeight() - topMargin - bottomMargin + 16; if (border == null) { // By setting colors here, we avoid recalculating them // over and over. border = new BevelBorder( BevelBorder.LOWERED, getBackground().brighter().brighter(), getBackground().brighter(), getBackground().darker().darker(), getBackground().darker()); } border.paintBorder(this, g, r.x, r.y, r.width, r.height); // Fill background color g.setColor(bgColor); g.fillRect(r.x + 2, r.y + 2, r.width - 4, r.height - 4); g.setColor(oldColor); long tMin = Long.MAX_VALUE; long tMax = Long.MIN_VALUE; long vMin = Long.MAX_VALUE; long vMax = 1; int w = getWidth() - rightMargin - leftMargin - 10; int h = getHeight() - topMargin - bottomMargin; if (times.size > 1) { tMin = Math.min(tMin, times.time(0)); tMax = Math.max(tMax, times.time(times.size - 1)); } long viewRangeMS; if (viewRange > 0) { viewRangeMS = viewRange * MINUTE; } else { // Display full time range, but no less than a minute viewRangeMS = Math.max(tMax - tMin, 1 * MINUTE); } // Calculate min/max values for (Sequence seq : seqs) { if (seq.size > 0) { for (int i = 0; i < seq.size; i++) { if (seq.size == 1 || times.time(i) >= tMax - viewRangeMS) { long val = seq.value(i); if (val > Long.MIN_VALUE) { vMax = Math.max(vMax, val); vMin = Math.min(vMin, val); } } } } else { vMin = 0L; } if (unit == Unit.BYTES || !seq.isPlotted) { // We'll scale only to the first (main) value set. // TODO: Use a separate property for this. break; } } // Normalize scale vMax = normalizeMax(vMax); if (vMin > 0) { if (vMax / vMin > 4) { vMin = 0; } else { vMin = normalizeMin(vMin); } } g.setColor(fg); // Axes // Draw vertical axis int x = leftMargin - 18; int y = topMargin; FontMetrics fm = g.getFontMetrics(); g.drawLine(x, y, x, y + h); int n = 5; if (("" + vMax).startsWith("2")) { n = 4; } else if (("" + vMax).startsWith("3")) { n = 6; } else if (("" + vMax).startsWith("4")) { n = 4; } else if (("" + vMax).startsWith("6")) { n = 6; } else if (("" + vMax).startsWith("7")) { n = 7; } else if (("" + vMax).startsWith("8")) { n = 8; } else if (("" + vMax).startsWith("9")) { n = 3; } // Ticks ArrayList<Long> tickValues = new ArrayList<Long>(); tickValues.add(vMin); for (int i = 0; i < n; i++) { long v = i * vMax / n; if (v > vMin) { tickValues.add(v); } } tickValues.add(vMax); n = tickValues.size(); String[] tickStrings = new String[n]; for (int i = 0; i < n; i++) { long v = tickValues.get(i); tickStrings[i] = getSizeString(v, vMax); } // Trim trailing decimal zeroes. if (decimals > 0) { boolean trimLast = true; boolean removedDecimalPoint = false; do { for (String str : tickStrings) { if (!(str.endsWith("0") || str.endsWith("."))) { trimLast = false; break; } } if (trimLast) { if (tickStrings[0].endsWith(".")) { removedDecimalPoint = true; } for (int i = 0; i < n; i++) { String str = tickStrings[i]; tickStrings[i] = str.substring(0, str.length() - 1); } } } while (trimLast && !removedDecimalPoint); } // Draw ticks int lastY = Integer.MAX_VALUE; for (int i = 0; i < n; i++) { long v = tickValues.get(i); y = topMargin + h - (int) (h * (v - vMin) / (vMax - vMin)); g.drawLine(x - 2, y, x + 2, y); String s = tickStrings[i]; if (unit == Unit.PERCENT) { s += "%"; } int sx = x - 6 - fm.stringWidth(s); if (y < lastY - 13) { if (checkLeftMargin(sx)) { // Wait for next repaint return; } g.drawString(s, sx, y + 4); } // Draw horizontal grid line g.setColor(Color.lightGray); g.drawLine(r.x + 4, y, r.x + r.width - 4, y); g.setColor(fg); lastY = y; } // Draw horizontal axis x = leftMargin; y = topMargin + h + 15; g.drawLine(x, y, x + w, y); long t1 = tMax; if (t1 <= 0L) { // No data yet, so draw current time t1 = System.currentTimeMillis(); } long tz = timeDF.getTimeZone().getOffset(t1); long tickInterval = calculateTickInterval(w, 40, viewRangeMS); if (tickInterval > 3 * HOUR) { tickInterval = calculateTickInterval(w, 80, viewRangeMS); } long t0 = tickInterval - (t1 - viewRangeMS + tz) % tickInterval; while (t0 < viewRangeMS) { x = leftMargin + (int) (w * t0 / viewRangeMS); g.drawLine(x, y - 2, x, y + 2); long t = t1 - viewRangeMS + t0; String str = formatClockTime(t); g.drawString(str, x, y + 16); // if (tickInterval > (1 * HOUR) && t % (1 * DAY) == 0) { if ((t + tz) % (1 * DAY) == 0) { str = formatDate(t); g.drawString(str, x, y + 27); } // Draw vertical grid line g.setColor(Color.lightGray); g.drawLine(x, topMargin, x, topMargin + h); g.setColor(fg); t0 += tickInterval; } // Plot values int start = 0; int nValues = 0; int nLists = seqs.size(); if (nLists > 0) { nValues = seqs.get(0).size; } if (nValues == 0) { g.setColor(oldColor); return; } else { Sequence seq = seqs.get(0); // Find starting point for (int p = 0; p < seq.size; p++) { if (times.time(p) >= tMax - viewRangeMS) { start = p; break; } } } // Optimization: collapse plot of more than four values per pixel int pointsPerPixel = (nValues - start) / w; if (pointsPerPixel < 4) { pointsPerPixel = 1; } // Draw graphs // Loop backwards over sequences because the first needs to be painted on top for (int i = nLists - 1; i >= 0; i--) { int x0 = leftMargin; int y0 = topMargin + h + 1; Sequence seq = seqs.get(i); if (seq.isPlotted && seq.size > 0) { // Paint twice, with white and with color for (int pass = 0; pass < 2; pass++) { g.setColor((pass == 0) ? Color.white : seq.color); int x1 = -1; long v1 = -1; for (int p = start; p < nValues; p += pointsPerPixel) { // Make sure we get the last value if (pointsPerPixel > 1 && p >= nValues - pointsPerPixel) { p = nValues - 1; } int x2 = (int) (w * (times.time(p) - (t1 - viewRangeMS)) / viewRangeMS); long v2 = seq.value(p); if (v2 >= vMin && v2 <= vMax) { int y2 = (int) (h * (v2 - vMin) / (vMax - vMin)); if (x1 >= 0 && v1 >= vMin && v1 <= vMax) { int y1 = (int) (h * (v1 - vMin) / (vMax - vMin)); if (y1 == y2) { // fillrect is much faster g.fillRect(x0 + x1, y0 - y1 - pass, x2 - x1, 1); } else { Graphics2D g2d = (Graphics2D) g; Stroke oldStroke = null; if (seq.transitionStroke != null) { oldStroke = g2d.getStroke(); g2d.setStroke(seq.transitionStroke); } g.drawLine(x0 + x1, y0 - y1 - pass, x0 + x2, y0 - y2 - pass); if (oldStroke != null) { g2d.setStroke(oldStroke); } } } } x1 = x2; v1 = v2; } } // Current value long v = seq.value(seq.size - 1); if (v >= vMin && v <= vMax) { if (bgIsLight) { g.setColor(seq.color); } else { g.setColor(fg); } x = r.x + r.width + 2; y = topMargin + h - (int) (h * (v - vMin) / (vMax - vMin)); // a small triangle/arrow g.fillPolygon(new int[] {x + 2, x + 6, x + 6}, new int[] {y, y + 3, y - 3}, 3); } g.setColor(fg); } } int[] valueStringSlots = new int[nLists]; for (int i = 0; i < nLists; i++) valueStringSlots[i] = -1; for (int i = 0; i < nLists; i++) { Sequence seq = seqs.get(i); if (seq.isPlotted && seq.size > 0) { // Draw current value // TODO: collapse values if pointsPerPixel >= 4 long v = seq.value(seq.size - 1); if (v >= vMin && v <= vMax) { x = r.x + r.width + 2; y = topMargin + h - (int) (h * (v - vMin) / (vMax - vMin)); int y2 = getValueStringSlot(valueStringSlots, y, 2 * 10, i); g.setFont(smallFont); if (bgIsLight) { g.setColor(seq.color); } else { g.setColor(fg); } String curValue = getFormattedValue(v, true); if (unit == Unit.PERCENT) { curValue += "%"; } int valWidth = fm.stringWidth(curValue); String legend = (displayLegend ? seq.name : ""); int legendWidth = fm.stringWidth(legend); if (checkRightMargin(valWidth) || checkRightMargin(legendWidth)) { // Wait for next repaint return; } g.drawString(legend, x + 17, Math.min(topMargin + h, y2 + 3 - 10)); g.drawString(curValue, x + 17, Math.min(topMargin + h + 10, y2 + 3)); // Maybe draw a short line to value if (y2 > y + 3) { g.drawLine(x + 9, y + 2, x + 14, y2); } else if (y2 < y - 3) { g.drawLine(x + 9, y - 2, x + 14, y2); } } g.setFont(oldFont); g.setColor(fg); } } g.setColor(oldColor); }
private void draw() { Renderer renderer = ui.getRenderer(); Graphics g = renderer.getGraphics(); int fsize = g.getFont().getSize(); JPanel target = ui.getDrawTarget(); g.setColor(Color.GRAY); g.fillRect(0, 0, target.getWidth(), target.getHeight()); Map<CabinType, Integer> xmap = new HashMap<CabinType, Integer>() { { this.put(CabinType.LEFT, Floor.PIXEL_WIDTH + 10); this.put(CabinType.RIGHT, Floor.PIXEL_WIDTH + 10 + Cabin.PIXEL_WIDTH + 30); } }; for (CabinType type : cabins.keySet()) { Integer x = xmap.get(type); Cabin cabin = cabins.get(type); int passengers = cabin.getPassengers().size(); double cabinY = cabin.getPosition() * REAL_TO_PIXEL_RATIO, cabinH = (double) cabin.PIXEL_HEIGHT, cabinW = (double) cabin.PIXEL_WIDTH; g.setColor(Color.WHITE); g.fillRect(x, (int) cabinY, (int) cabinW, (int) cabinH); g.setColor(Color.BLACK); g.drawRect(x, (int) cabinY, (int) cabinW, (int) cabinH); // cabin fullness g.drawString( passengers >= cabinLimitPeople ? passengers > cabinLimitPeople ? "초과" : "만원" : "", (int) (x + cabinW / 2.0 - fsize), (int) (cabinY + cabinH / 2.0 - fsize)); // passengers on cabin g.drawString( String.format("%d명", passengers), (int) (x + cabinW / 2.0 - fsize * 2.0 / 2.0), (int) (cabinY + cabinH / 2.0)); // cabin weight g.drawString(String.format("%.0fkg", mass(cabin)), x, (int) (cabinY + cabinH / 2.0 + fsize)); // cabin speed g.drawString( String.format("%.1fm/s", Math.abs(cabin.getVelocity())), x, (int) (cabinY + cabinH / 2.0 + fsize * 2.0)); } for (Floor floor : floors.values()) { int passengers = floor.getPassengers().size(); double floorY = floor.getPosition() * REAL_TO_PIXEL_RATIO; g.setFont(Font.getFont(Font.SANS_SERIF)); g.setColor(Color.WHITE); g.fillRect(1, (int) floorY, Floor.PIXEL_WIDTH, Floor.PIXEL_HEIGHT); g.setColor(Color.BLACK); g.drawRect(1, (int) floorY, Floor.PIXEL_WIDTH, Floor.PIXEL_HEIGHT); g.drawString(floor.getNum() + "층", 1, (int) floorY + 15); g.drawString( Integer.toString(passengers), (int) (1 + (double) (Floor.PIXEL_WIDTH) / 2.0 - (double) fsize / 2.0), (int) (floorY + (double) Floor.PIXEL_HEIGHT / 2.0)); } if (state >> 1 == CircumstanceType.FIRE.state()) { Floor firedFloor = (Floor) Circumstance.get(CircumstanceType.FIRE).getParameter("floor"); if (null != firedFloor) g.drawString( "화재", Floor.PIXEL_WIDTH / 2 - fsize, (int) (firedFloor.getPosition() * REAL_TO_PIXEL_RATIO + (double) Floor.PIXEL_HEIGHT / 2.0 + fsize * 2.0)); } renderer.flush(); }
public void paint(Graphics g) { Rectangle r = bounds(); // paint the box int width = r.width - TF_LEFT + TF_RIGHT; if (width < 0) width = 0; int height = r.height - TF_TOP + TF_BOTTOM; if (height < 0) height = 0; if (r.width > lastWidth) firstVisibleTab = 0; lastWidth = r.width; int col = TF_LEFT; int row; Color c = g.getColor(); g.setColor(getBackground()); g.fillRect(0, 0, r.width, r.height); if (iTabsPosition == TOP) row = TF_TOP; else row = TF_TOP - TF_BTN_HEIGHT; // draw border g.setColor(Color.white); g.drawLine(col, row, (col + width - 1), row); g.drawLine(col, row, col, (row + height - 1)); g.setColor(Color.gray); g.drawLine((col + 2), (row + height - 2), (col + width - 2), (row + height - 2)); g.drawLine((col + width - 2), (row + 2), (col + width - 2), (row + height - 2)); g.setColor(Color.black); g.drawLine((col + 1), (row + height - 1), (col + width - 1), (row + height - 1)); g.drawLine((col + width - 1), (row + 1), (col + width - 1), (row + height - 1)); // paint the tabs, and record areas int x1; int x2 = TF_LEFT + 8; int y1; int y2; int x3 = 0; int x4 = TF_LEFT; int sze = pages.size(); String sLabel; Font f = g.getFont(); FontMetrics fm = getFontMetrics(fReg); FontMetrics fms = getFontMetrics(fSel); int labelWidth = 0; Polygon p; int w; NotebookPage[] npages = new NotebookPage[sze]; for (w = 0; w < sze; ++w) { npages[w] = (NotebookPage) pages.elementAt(w); npages[w].poly = nullPoly; } // make sure there is a polygon for each tab if (firstVisibleTab > 0) x4 += 2; int xStep = 1; for (w = firstVisibleTab; w < sze; w++) { int fheight = fm.getHeight() - fms.getDescent(); if (w == curIndex) fheight = fms.getHeight() - fms.getDescent(); p = new Polygon(); if (npages[w].hidden) { y1 = TF_TOP - TF_BTN_HEIGHT; y2 = TF_TOP - 1; x1 = x4 - 1; x2 = x1 + 1; x3 = x1; x4 = x2; p.addPoint(x1, y1); p.addPoint(x1, y2); p.addPoint(x2, y2); p.addPoint(x2, y1); npages[w].poly = p; // xStep++; continue; } try { sLabel = npages[w].label; if (w == curIndex) labelWidth = fms.stringWidth(sLabel); else labelWidth = fm.stringWidth(sLabel); if (npages[w].img != null) labelWidth += IMAGE_SIZE; if (iTabsPosition == TOP) { y1 = TF_TOP - TF_BTN_HEIGHT; y2 = TF_TOP - 1; } else { y1 = r.height + TF_BOTTOM + 1; y2 = r.height + TF_BOTTOM - TF_BTN_HEIGHT; } if (iTabsStyle == ROUNDED) { x1 = x4 + 2; x2 = x1 + labelWidth + 13; } else { x1 = x2 - 7; x2 = x1 + labelWidth + 28; } // check to see if this tab would draw too far if ((x2 + 36 - TF_RIGHT) > r.width) break; // draw the outside edge of the tab if (iTabsPosition == TOP) { // if current tab, it extends further if (w == curIndex) { y1 -= 3; x1 -= 2; } g.setColor(Color.white); g.drawLine(x1 + 2, y1, x2, y1); // draw the border between tabs if not covered by the current one g.drawLine(x1, y1 + 2, x1, y2); x3 = x1; g.drawLine(x1 + 1, y1 + 1, x1 + 1, y1 + 1); g.setColor(Color.gray); g.drawLine(x2, y1, x2, y2); g.setColor(Color.black); g.drawLine(x2 + 1, y1 + 2, x2 + 1, y2); x4 = x2; } else { if (iTabsStyle == SQUARE) { g.setColor(Color.gray); g.drawLine(x1 + 9, y1, x2 - 9, y1); g.setColor(Color.black); // left \ slanted line if (w == 0 || w == curIndex) { g.drawLine(x1, y2, x1 + 9, y1); p.addPoint(x1, y2); } else { g.drawLine(x1 + 4, y1 - 9, x1 + 9, y1); p.addPoint(x1 + 9, y2); p.addPoint(x1 + 4, y1 - 9); } p.addPoint(x1 + 9, y1); p.addPoint(x2 - 9, y1); if ((w + xStep) == curIndex) { g.drawLine(x2 - 5, y1 - 9, x2 - 9, y1); p.addPoint(x2 - 5, y1); p.addPoint(x2 - 9, y2); } else { g.drawLine(x2, y2, x2 - 9, y1); p.addPoint(x2, y2); } if (w == 1 || w == curIndex) p.addPoint(x1, y2); else p.addPoint(x1 + 9, y2); } else { // if current tab, it extends further if (w == curIndex) { y1 += 3; x1 -= 2; } g.setColor(Color.white); if (curIndex == (w + xStep)) g.drawLine(x1 + 2, y1, x2 - 2, y1); else g.drawLine(x1 + 2, y1, x2, y1); // draw the border between tabs if not covered by the current one if (curIndex != (w - xStep)) { g.drawLine(x1, y1 - 2, x1, y2); x3 = x1; } else x3 = x1 + 1; g.drawLine(x1 + 1, y1 - 1, x1 + 1, y1 - 1); if (curIndex != (w + xStep)) { g.setColor(Color.gray); g.drawLine(x2, y1, x2, y2); g.setColor(Color.black); g.drawLine(x2 + 1, y1 - 2, x2 + 1, y2); x4 = x2; } else x4 = x2 - 1; } } // draw the inside edge of the tab if (w == curIndex) { if (iTabsPosition == TOP) ++y2; else --y2; g.setColor(getBackground()); g.drawLine(x1 + 1, y2, x2, y2); if (iTabsPosition == BOTTOM) g.drawLine(x1 + 1, y2 - 1, x2, y2 - 1); g.setFont(fSel); } else g.setFont(fReg); // if (iTabsPosition == TOP) if (iTabsStyle == ROUNDED) { p.addPoint(x3 - 1, y2 + 1); p.addPoint(x4 + 1, y2 + 1); p.addPoint(x4 + 1, y1 - 1); p.addPoint(x3 + 2, y1 - 1); p.addPoint(x3 - 1, y1 + 2); p.addPoint(x3 - 1, y2 + 1); } npages[w].poly = p; g.setColor(npages[w].color); Polygon p2 = justPolygon(p, iTabsPosition == TOP); g.fillPolygon(p2); // Boolean bool = (Boolean) vEnabled.elementAt(w); // if (bool.booleanValue()) g.setColor(caption); // else // g.setColor(Color.gray); int dx = (npages[w].img == null) ? 0 : IMAGE_SIZE; int xx = x1 + 8 + dx; int yy = y1 + 15; if (iTabsStyle == TOP) { } else if (iTabsStyle == ROUNDED) { yy = y1 - 6; } else { xx = x1 + 14 + dx; yy = y1 - 4; } int imgy = yy - fheight / 2; if (npages[w].img != null) { int imgH = npages[w].img.getHeight(this); int imgW = npages[w].img.getWidth(this); imgy = imgy - imgH / 2 + 1; g.drawImage(npages[w].img, xx - IMAGE_SIZE - 2, imgy, imgW, imgH, this); } g.drawString(sLabel, xx, yy); } catch (ArrayIndexOutOfBoundsException e) { } xStep = 1; } // do I need to show arrows because there are too many tabs??? if ((firstVisibleTab > 0) || (w < sze)) { dbLeft.show(); dbRight.show(); if (firstVisibleTab > 0) dbLeft.enable(); else dbLeft.disable(); if (w < sze) dbRight.enable(); else dbRight.disable(); } else { dbLeft.hide(); dbRight.hide(); } g.setFont(f); g.setColor(c); if (mark && curIndex >= 0) drawMark(g, npages[curIndex].poly); npages = null; }