/* name: stk_shapes.cc info: basic drawings of stk such as buttons, labels, radiobuttons, sliders and so on - implementation author: Dusan Halicky (dvh.tosomja@post.sk) licence: GNU GPL history: 2005-09-27 - start of developement 2005-11-01 - fixed warning of unused variable 2005-11-10 - optimized drawings todo: - finish and release this bugs: - */ // system header files #include #include #include #include // local header files #include "stk_constants.h" #include "stk_functions.h" #include "stk_colors.h" #include "stk_display.h" #include "stk_font.h" #include "stk_init.h" // this file header #include "stk_shapes.h" // debugging #ifdef STK_DEBUG #define STK_SHAPES_DEBUG #define STK_SHAPES_DEBUG_DRAW_LABEL #endif // slow drawing - very good for optimization of draw speed (implemented initially for improve slider redraw performance) #define no_STK_SHAPES_SLEEP #define stk_shapes_sleep() { \ XFlush(stkdisplay); \ stk_sleep(100); \ } // implementation void stk_draw_string(Drawable d, GC gc, XFontStruct *font, int x, int y, char* caption, int color) { // draw string on display with selected color XSetForeground(stkdisplay,gc,stkcolors[color].pixel); XSetFont(stkdisplay,gc,font->fid); XDrawString(stkdisplay,d,gc,x,y+font->descent,caption,strlen(caption)); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_slider_button(Display *display, Drawable d, GC gc, int x, int y, int w, int h, int orientation, bool active) { /* button for slider, now only default 0 _ _ _ __ 0,1,2 = [_] 3 = [_> 4 = <_] 5 = | | 6 = /\ \/ |__| 0 = STK_SLIDER_UNIVERSAL 1 = STK_SLIDER_VERTICAL 2 = STK_SLIDER_HORIZONTAL 3 = STK_SLIDER_VERTICAL_RIGHT 4 = STK_SLIDER_VERTICAL_LEFT 5 = STK_SLIDER_HORIZONTAL_DOWN 6 = STK_SLIDER_HORIZONTAL_UP */ // univerzal // gray interior if (active) XSetForeground(display,gc,stkcolors[STK_COLOR_ACTIVE].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XFillRectangle(display,d,gc,x,y,w,h); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif // shaded frame // outer left-up white border XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XDrawLine(display,d,gc,x,y,x+w,y); XDrawLine(display,d,gc,x,y,x,y+h); // outter right-down dark gray border XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_GRAY].pixel); XDrawLine(display,d,gc,x+w,y+h,x+w,y); XDrawLine(display,d,gc,x+w,y+h,x,y+h); // internal left-down gray XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawLine(display,d,gc,x+w-1,y+h-1,x+w-1,y+1); XDrawLine(display,d,gc,x+w-1,y+h-1,x+1,y+h-1); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_frame(Display *display, Drawable d, GC gc, int x, int y, int w, int h, bool enabled) { // frame with white center pushed which is used by e.g. edit, memo, compo or slider // white interior if enabled, gray if disabled if (enabled) XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XFillRectangle(display,d,gc,x,y,w,h); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif // shaded frame pressed // outter left-up dark gray XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawLine(display,d,gc,x,y,x+w,y); XDrawLine(display,d,gc,x,y,x,y+h); // internal left-up black XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_GRAY].pixel); XDrawLine(display,d,gc,x+1,y+1,x+w-2,y+1); XDrawLine(display,d,gc,x+1,y+1,x+1,y+h-2); // outer right down white XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XDrawLine(display,d,gc,x+w,y+h,x+w,y); XDrawLine(display,d,gc,x+w,y+h,x,y+h); // internal right down light gray XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XDrawLine(display,d,gc,x+w-1,y+h-1,x+w-1,y+1); XDrawLine(display,d,gc,x+w-1,y+h-1,x+1,y+h-1); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_label(Display *display, Drawable d, GC gc, XFontStruct *font_struct, int x, int y, int *w, int *h, int oldw, int oldh, char *caption, bool enabled, bool active, bool correction, bool fillrect) { // this show label caption, also with underscore encoded by character & before, draw label in its current state (enabled, active). // used by button, label, radiobutton, ... // get the proportions of caption (begining and position, by the character & in caption) // this function return size in parameter *w and *h char shortcut_char; char *pomocny_prefix; char *decoded_caption; #ifdef STK_SHAPES_DEBUG_DRAW_LABEL printf("stk_draw_label (caption='%s' w=%d h=%d ow=%d oh=%d)\n",caption,(int)w,(int)h,oldw,oldh); #endif decoded_caption = stk_decode_caption(caption,&shortcut_char,&pomocny_prefix); #ifdef STK_SHAPES_DEBUG_DRAW_LABEL printf(" decoded_caption='%s' char='%c' caption_prefix='%s'\n",decoded_caption,shortcut_char,pomocny_prefix); #endif int i, underscore_start, underscore_length; char *poms2; poms2=(char*)malloc(sizeof(char)*2); poms2[0]=shortcut_char; poms2[1]='\0'; #ifdef STK_SHAPES_DEBUG_DRAW_LABEL printf(" detecting underscore (caption_prefix='%s' len(poms2)=%d)...\n",pomocny_prefix,strlen(poms2)); #endif int neww,newh; stk_font_clip_rect(stkfont,decoded_caption,&neww,&newh); stk_font_clip_rect(stkfont,pomocny_prefix,&underscore_start,&i); stk_font_clip_rect(stkfont,poms2,&underscore_length,&i); #ifdef STK_SHAPES_DEBUG_DRAW_LABEL printf(" caption='%s' --> us=%d ul=%d \n",caption,underscore_start, underscore_length); #endif // redraw background (even with bigger size if required complete redraw - but this should be a artefact of STK v1.0) int maxw,maxh; maxw = neww; if (oldw > maxw) maxw = oldw; maxh = newh; if (oldh > maxh) maxh = oldh; XSetLineAttributes(display,gc,0,LineSolid,CapButt,JoinMiter); if (active) XSetForeground(display,gc,stkcolors[STK_COLOR_ACTIVE].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); // redraw the background - if forced?! if (fillrect) XFillRectangle(display,d,gc,x,y,maxw,maxh); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif // set return variables *w=neww; *h=newh; // show caption, gray if enabled=false else black int lc = strlen(decoded_caption); int dx = 0; if (correction) dx = int (underscore_length / 2.0); #ifdef STK_SHAPES_DEBUG_DRAW_LABEL printf(" dx=%d\n",dx); #endif //int px = (w-XTextWidth(font_struct,caption,lc)) / 2; if (enabled != true) XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_BLACK].pixel); XSetFont(display,gc,stkfont->fid); XDrawString(display,d,gc,x,y+newh-stkfont_cor,decoded_caption,lc); // draw underscore if (underscore_length>0) { XDrawLine(display,d,gc,x+underscore_start/*+dx*/,y+newh-1,x/*+dx*/+underscore_start+underscore_length-2,y+newh-1); } // release aux variables free(poms2); free(pomocny_prefix); free(decoded_caption); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_radiobutton(Display *display, Drawable d, GC gc, XFontStruct *font_struct, int x, int y, int w, int h, int oldw, int oldh, int button_width, char *caption, bool enabled, bool active, bool focused, bool checked) { // this shows radiobutton with its state // bitmap - not drawn now, we will need a bitmap here to do that, but bitmaps belongs to windows, but we don't have them here // ................... // caption (shifted to make space for bitmap) int cw, ch; stk_draw_label(display,d,gc,font_struct,x+button_width+2,y,&cw,&ch,oldw,oldh,caption,enabled,active); // dotted focus frame over the caption if (focused) stk_draw_focus_rectangle(display,d,gc,x+button_width+2,y,cw+3,ch-1); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_button_frame(Display *display, Drawable d, GC gc, int x, int y, int w, int h, bool pressed, bool focused, bool cleanup) { // draw button frame - the border, usually 2px width, 3D look - dependent of "down" state if (cleanup) { XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XDrawRectangle(display,d,gc,0,0,w-1,h-1); XDrawRectangle(display,d,gc,1,1,w-3,h-3); XDrawRectangle(display,d,gc,2,2,w-5,h-5); // stk_shapes_sleep(); } if (pressed) { // yes, it is pressed // black border around it XSetForeground(display,gc,stkcolors[STK_COLOR_BLACK].pixel); XDrawRectangle(display,d,gc,x,y,w-1,h-1); // internal dark shadow XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawRectangle(display,d,gc,x+1,y+1,w-3,h-3); } else { // not pressed // is it focused ??? if (focused) { // not pressed but focused // black border around XSetForeground(display,gc,stkcolors[STK_COLOR_BLACK].pixel); XDrawRectangle(display,d,gc,x,y,w-1,h-1); // white lighted part XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XDrawLine(display,d,gc,x+1,y+1,x+w-2,y+1); XDrawLine(display,d,gc,x+1,y+h-2,x+1,y+1); // dark shadow XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_GRAY].pixel); XDrawLine(display,d,gc,x+w-2,y+1,x+w-2,y+h-2); XDrawLine(display,d,gc,x+w-2,y+h-2,x+1,y+h-2); // light shadow XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawLine(display,d,gc,x+w-3,y+2,x+w-3,y+h-3); XDrawLine(display,d,gc,x+w-3,y+h-3,x+2,y+h-3); } else { // not pressed and not focused // lighted part white XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XDrawLine(display,d,gc,x,y,x+w,y); XDrawLine(display,d,gc,x,y+h,x,y); // dark shadow XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_GRAY].pixel); XDrawLine(display,d,gc,x+w-1,y,x+w-1,y+h-1); XDrawLine(display,d,gc,x+w-1,y+h-1,x,y+h-1); // light shadow - internal XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawLine(display,d,gc,x+w-2,y+1,x+w-2,y+h-2); XDrawLine(display,d,gc,x+w-2,y+h-2,x+1,y+h-2); // printf("zzzzzzz (x=%d, y=%d, w=%d, h=%d, f=%d, p=%d, c=%d)\n",x,y,w,h,(int)focused,int(pressed),(int)cleanup); } }; #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_button(Display *display, Drawable d, GC gc, XFontStruct *font_struct, int x, int y, int w, int h, char *caption, bool enabled, bool focused, bool pressed, bool active) { // draw the button with the current state #ifdef STK_SHAPES_DEBUG printf("stk_draw_button: display=0x%X window=0x%X gc=0x%X font_struct=0x%X x=%d y=%d w=%d h=%d caption='%s' enb=%d foc=%d pres=%d act=%d\n", (int)display,(int)d,(int)gc,(int)font_struct,x,y,w,h,caption,enabled,focused,pressed,active); #endif // unsigned int pomf; // face of button - light gray XSetLineAttributes(display,gc,0,LineSolid,CapButt,JoinMiter); if (active) XSetForeground(display,gc,stkcolors[STK_COLOR_ACTIVE].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XFillRectangle(display,d,gc,x,y,w,h); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif // pressed button? stk_draw_button_frame(display,d,gc,x,y,w,h,pressed,focused,false); // show caption (gray if not enabled, else black), little shifted if pressed // centred caption int tw, th; stk_font_clip_rect(stkfont,caption,&tw,&th,true); int px = (w-tw) / 2; int cw = tw; int ch = 0; if (pressed) stk_draw_label(display,d,gc,font_struct,x+px+1,y+(h-th)/2,&cw,&ch,cw,ch,caption,enabled,active); else stk_draw_label(display,d,gc,font_struct,x+px+1,y+(h-th)/2,&cw,&ch,cw,ch,caption,enabled,active); // focus dotted rectangle if (focused) stk_draw_focus_rectangle(display,d,gc,x+4,y+4,w-8,h-8); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_rectangle(Display *display, Drawable d, GC gc, int x, int y, int w, int h, unsigned long color_index) { // show simple rectangle with selected STK color if (color_index > STK_COLOR_LAST) { printf("stk_shapes: color out of range\n"); } XSetForeground(display,gc,stkcolors[color_index].pixel); XDrawRectangle(display,d,gc,x,y,w,h); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_focus_rectangle(Display *display, Drawable d, GC gc, int x, int y, int w, int h) { // show dotted focus rectangle XDrawRectangle(display,d,stkgc_focus,x,y,w-1,h-1); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_fill_rectangle(Display *display, Drawable d, GC gc, int x, int y, int w, int h, unsigned long color_index) { // fill rectangle with selected STK color if (color_index > STK_COLOR_LAST) { printf("stk_shapes: color out of range\n"); } XSetForeground(display,gc,stkcolors[color_index].pixel); XFillRectangle(display,d,gc,x,y,w,h); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_slider_bg_horiz(Display *display, Drawable d, GC gc, int x, int y, int w, int h, int a, int b) { // draw the slider's background | window_color rect | 1px gray | 1px black | white rect | 1px window_color | 1px white | window_color rect | // y=0 a a+1 a+2 b b+1 w or h XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XFillRectangle(display,d,gc,x,y,w,a); XFillRectangle(display,d,gc,x,y+b,w,h-b); XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XFillRectangle(display,d,gc,x,y+a,w,b-a); XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawLine(display,d,gc,x,y+a+0,x+w-1,y+a+0); XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_GRAY].pixel); XDrawLine(display,d,gc,x,y+a+1,x+w-1,y+a+1); XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XDrawLine(display,d,gc,x,y+b-2,x+w-1,y+b-2); } void stk_draw_slider_bg_vert(Display *display, Drawable d, GC gc, int x, int y, int w, int h, int a, int b) { // draw the slider's backround XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XFillRectangle(display,d,gc,x,y,a,h); XFillRectangle(display,d,gc,x+b,y,w-b,h); XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XFillRectangle(display,d,gc,x+a,y,b-a,h); XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); XDrawLine(display,d,gc,x+a+0,y,x+a+0,y+h-1); XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_GRAY].pixel); XDrawLine(display,d,gc,x+a+1,y,x+a+1,y+h-1); XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XDrawLine(display,d,gc,x+b-2,y,x+b-2,y+h-1); } void stk_draw_text_cursor(Display *display, Drawable d, GC gc, int x, int y, int h, bool visible, bool enabled) { // draw (or hide) the text cursor | if (enabled) { if (visible) XSetForeground(display,gc,stkcolors[STK_COLOR_BLACK].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); } else { XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); } XDrawLine(display,d,gc,x,y,x,y+h); } void stk_draw_menuitem(Display *display, Drawable d, GC gc, XFontStruct *font_struct, int x, int y, int w, int h, char *caption, bool enabled, bool focused, bool active) { // draw the menu item with the current state #ifdef STK_SHAPES_DEBUG printf("stk_draw_menuitem: display=0x%X window=0x%X gc=0x%X font_struct=0x%X x=%d y=%d w=%d h=%d caption='%s' enb=%d foc=%d act=%d\n", (int)display,(int)d,(int)gc,(int)font_struct,x,y,w,h,caption,enabled,focused,active); #endif // face of button - light gray, blue if active if (active||focused) XSetForeground(display,gc,stkcolors[STK_COLOR_DARK_BLUE].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_WINDOW].pixel); XFillRectangle(display,d,gc,x,y,w,h); #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif // show caption (gray if not enabled, else black), little shifted if pressed if (active||focused) XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); else { if (enabled) XSetForeground(display,gc,stkcolors[STK_COLOR_BLACK].pixel); else XSetForeground(display,gc,stkcolors[STK_COLOR_GRAY].pixel); } // centered caption // int tw, th; // stk_font_clip_rect(font_struct,caption,&tw,&th,false); if (caption!=NULL) { // normal caption XSetFont(display,gc,font_struct->fid); XDrawString(display,d,gc,x+h-2*2,y+h-font_struct->descent-2,caption,strlen(caption)); } else { // separator --------- XDrawLine(display,d,gc,x+1,y+1,x+w-2,y+1); XSetForeground(display,gc,stkcolors[STK_COLOR_WHITE].pixel); XDrawLine(display,d,gc,x+1,y+2,x+w-2,y+2); } #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } void stk_draw_panel(Display *display, Drawable d, GC gc, int x, int y, int w, int h, int border, bool enabled, bool active) { // this show panel with border #ifdef STK_SHAPES_DEBUG printf("stk_draw_panel (d=0x%X x=%d y=%d w=%d h=%d)\n",(int)d,(int)x,(int)y,(int)w,(int)h); #endif // border unsigned int c1,c2; c1 = stkcolors[STK_COLOR_DARK_SHADOW].pixel; c2 = stkcolors[STK_COLOR_LIGHT_SHADOW].pixel; if (border == 1) c2 = c1; if ((border == 3) || (border == 5)) { int i = c1; c1 = c2; c2 = i; } // set line attr. XSetLineAttributes(display,gc,0,LineSolid,CapButt,JoinMiter); // background XClearWindow(display,d); // border if (border > 0) { // light XSetForeground(display,gc,c1); XDrawLine(display,d,gc,0,0,w-1,0); XDrawLine(display,d,gc,0,0,0,h-1); // dark XSetForeground(display,gc,c2); XDrawLine(display,d,gc,w-1,0,w-1,h-1); XDrawLine(display,d,gc,0,h-1,w-1,h-1); // secondary (inner) border - pressed if (border == 4) { // light XSetForeground(display,gc,c2); XDrawLine(display,d,gc,1,1,w-2,1); XDrawLine(display,d,gc,1,1,1,h-2); // dark XSetForeground(display,gc,c1); XDrawLine(display,d,gc,w-2,1,w-2,h-2); XDrawLine(display,d,gc,1,h-2,w-2,h-2); } // relief if (border == 5) { // light XSetForeground(display,gc,c2); XDrawLine(display,d,gc,1,1,w-2,1); XDrawLine(display,d,gc,1,1,1,h-2); // dark XSetForeground(display,gc,c1); XDrawLine(display,d,gc,w-2,1,w-2,h-2); XDrawLine(display,d,gc,1,h-2,w-2,h-2); } } #ifdef STK_SHAPES_SLEEP stk_shapes_sleep(); #endif } // end of file