1 /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. 2 * 3 * This is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This software is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this software; if not, write to the Free Software 15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 16 * USA. 17 */ 18 // 19 // TXLabel.h 20 // 21 // An TXLabel allows you to put up multiline text in a window with various 22 // alignments. The label must be big enough to contain the text - if not then 23 // it will be resized appropriately. 24 // 25 26 #ifndef __TXLABEL_H__ 27 #define __TXLABEL_H__ 28 29 #include <stdlib.h> 30 #include "TXWindow.h" 31 #include <rfb/util.h> 32 33 class TXLabel : public TXWindow, public TXEventHandler { 34 public: 35 enum HAlign { left, centre, right }; 36 enum VAlign { top, middle, bottom }; 37 38 TXLabel(Display* dpy_, const char* text_, TXWindow* parent_=0, 39 int w=1, int h=1, HAlign ha=centre, VAlign va=middle) TXWindow(dpy_,w,h,parent_)40 : TXWindow(dpy_, w, h, parent_), lineSpacing(2), lines(0), 41 halign(ha), valign(va) 42 { 43 setEventHandler(this); 44 setText(text_); 45 addEventMask(ExposureMask); 46 } 47 48 // setText() changes the text in the label. setText(const char * text_)49 void setText(const char* text_) { 50 text.buf = rfb::strDup(text_); 51 lines = 0; 52 int lineStart = 0; 53 int textWidth = 0; 54 int i = -1; 55 do { 56 i++; 57 if (text.buf[i] == '\n' || text.buf[i] == 0) { 58 int tw = XTextWidth(defaultFS, &text.buf[lineStart], i-lineStart); 59 if (tw > textWidth) textWidth = tw; 60 lineStart = i+1; 61 lines++; 62 } 63 } while (text.buf[i] != 0); 64 int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing) 65 * lines); 66 int newWidth = __rfbmax(width(), textWidth + xPad*2); 67 int newHeight = __rfbmax(height(), textHeight + yPad*2); 68 if (width() < newWidth || height() < newHeight) { 69 resize(newWidth, newHeight); 70 } 71 invalidate(); 72 } 73 74 private: xOffset(int textWidth)75 int xOffset(int textWidth) { 76 switch (halign) { 77 case left: return xPad; 78 case right: return width() - xPad - textWidth; 79 default: return (width() - textWidth) / 2; 80 } 81 } 82 yOffset(int lineNum)83 int yOffset(int lineNum) { 84 int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing) 85 * lines); 86 int lineOffset = ((defaultFS->ascent + defaultFS->descent + lineSpacing) 87 * lineNum + defaultFS->ascent); 88 switch (valign) { 89 case top: return yPad + lineOffset; 90 case bottom: return height() - yPad - textHeight + lineOffset; 91 default: return (height() - textHeight) / 2 + lineOffset; 92 } 93 } 94 paint()95 void paint() { 96 int lineNum = 0; 97 int lineStart = 0; 98 int i = -1; 99 do { 100 i++; 101 if (text.buf[i] == '\n' || text.buf[i] == 0) { 102 int tw = XTextWidth(defaultFS, &text.buf[lineStart], i-lineStart); 103 XDrawString(dpy, win(), defaultGC, xOffset(tw), yOffset(lineNum), 104 &text.buf[lineStart], i-lineStart); 105 lineStart = i+1; 106 lineNum++; 107 } 108 } while (text.buf[i] != 0); 109 } 110 handleEvent(TXWindow * w,XEvent * ev)111 virtual void handleEvent(TXWindow* w, XEvent* ev) { 112 switch (ev->type) { 113 case Expose: 114 paint(); 115 break; 116 } 117 } 118 119 int lineSpacing; 120 rfb::CharArray text; 121 int lines; 122 HAlign halign; 123 VAlign valign; 124 }; 125 126 #endif 127