/* Terminality - a portable terminal handling library * Copyright (C) 1998-2002, Emil Mikulic. * This is LGPL - look at COPYING.LIB */ /* Project: Terminality/GUI * File: form.cpp * Author: Emil Mikulic * Description: Implement staticLabels, buttons and forms */ #include const char form_rcsid[] = "$Id: form.cpp,v 1.14 2002/07/26 01:39:40 darkmoon Exp $"; // Custom class // Initialise custom::custom(void (*dh)(void), void (*ch)(void)) { draw_handle = dh; chsch_handle = ch; reg_id = register_add(Custom, this); visible = fixed_colors = false; } // Destroy custom::~custom() { register_del(reg_id); } // Draw void custom::draw(void) { if(!visible || !draw_handle) return; (*draw_handle)(); } // Change scheme void custom::change_scheme(void) { if(!fixed_colors || !chsch_handle) return; (*chsch_handle)(); } staticLabel::staticLabel(int xx, int yy, char *str) { // encapsulate data x = xx; y = yy; fg = COLOR_SLABEL_FG; bg = COLOR_SLABEL_BG; s = (char *)xmalloc(strlen(str)+1); strcpy(s, str); visible = true; fixed_colors = false; } staticLabel::staticLabel(int xx, int yy, char *str, color f, color b) { // encapsulate data x = xx; y = yy; fg = f; bg = b; fixed_colors = true; s = (char *)xmalloc(strlen(str)+1); strcpy(s, str); visible = true; } staticLabel::~staticLabel() { xfree(s); } // Label change void staticLabel::set_label(char *buf) { xfree(s); s = (char *) xmalloc(strlen(buf) + 1); strcpy(s, buf); } // Drawing routine void staticLabel::draw(void) { if(!visible) return; gotoxy(x, y); setcolor(fg,bg); printw(s); } // Change color scheme void staticLabel::change_scheme(void) { if (fixed_colors) return; fg = COLOR_SLABEL_FG; bg = COLOR_SLABEL_BG; } button::button(int xx, int yy, int ww, int hh, const char *str, int _id) : formObject() { int ms; // encapsulate data focus = false; x = xx; y = yy; w = ww; h = hh; id = _id; ms = strlen(str) < (unsigned) ww ? strlen(str) : ww; s = (char *) xmalloc(ww + 1); strncpy(s, str, ww); s[ww] = 0; // Setup colors BACKGROUND = COLOR_BUTTON_BG; SELECTED_TL = COLOR_BUTTON_STL; BR = COLOR_BUTTON_BR; TEXT = COLOR_BUTTON_TEXT; TL = COLOR_BUTTON_TL; SELECTED_BR = COLOR_BUTTON_SBR; SEL_TEXT = COLOR_BUTTON_STEXT; DEF_TEXT = COLOR_BUTTON_DTEXT; SEL_DEF_TEXT = COLOR_BUTTON_SDTEXT; type_id = Button; visible = true; fixed_colors = false; dflt = false; } button::~button() { xfree(s); } // Get type of object int button::getid(void) { return id; // is a button } // Draw button void button::draw(void) { if(!visible) return; if(focus) box_3d(x, y, x+w+1, y+h+1, BACKGROUND, SELECTED_TL, SELECTED_BR); else box_3d(x, y, x+w+1, y+h+1, BACKGROUND, TL, BR); bgcolor(BACKGROUND); if(focus) if(dflt) fgcolor(SEL_DEF_TEXT); else fgcolor(SEL_TEXT); else if(dflt) fgcolor(DEF_TEXT); else fgcolor(TEXT); gotoxy(x+(w-strlen(s))/2+1, y+(h/2)+1); printw(s); } // Get choice int button::getnb(void) { key k; cursor cs = get_cursor(); bool old_vis = visible; visible = true; set_cursor(none); do { // Draw [now focused] button focus = true; draw(); update(); focus = false; // Get key k = readkey(); k = keyhandler(k, Button); k = handle_key(k, Button, this); // Handle it switch(k) { case KEY_ESC: set_cursor(cs); visible = old_vis; return 27; case KEY_UP: set_cursor(cs); visible = old_vis; return -1; case KEY_TAB: case KEY_DOWN: set_cursor(cs); visible = old_vis; return 1; case KEY_ENTER: case ' ': set_cursor(cs); visible = old_vis; return 0; case KEY_NOTHING: break; default: beep(); } } while(1); } // Change color scheme void button::change_scheme(void) { if(fixed_colors) return; BACKGROUND = COLOR_BUTTON_BG; SELECTED_TL = COLOR_BUTTON_STL; BR = COLOR_BUTTON_BR; TEXT = COLOR_BUTTON_TEXT; TL = COLOR_BUTTON_TL; SELECTED_BR = COLOR_BUTTON_SBR; SEL_TEXT = COLOR_BUTTON_STEXT; DEF_TEXT = COLOR_BUTTON_DTEXT; SEL_DEF_TEXT = COLOR_BUTTON_SDTEXT; } form::form(int xx, int yy, int ww, int hh) { x = xx; y = yy; w = ww; h = hh; objDyn = objStatic = NULL; TL = COLOR_FORM_TL; BR = COLOR_FORM_BR; BACKGROUND = COLOR_FORM_BG; draw_frame = true; visible = fixed_colors = false; reg_id = register_add(Form, this); remember_id = false; last_id = 0; } form::~form() { formStatic *tmp; formObject *tmp2; int i; for (i=0; idraw(); } // Draw dynamic objects for (i = 0; idraw(); } update_set(old_update); update(); } // Get data ... #define LGD(i) tn_list_getdata(objDyn, (i)) // Find next visible object int form::find_next_visible(int id) { int count = tn_list_size(objDyn); int i = count + 2; while(i--) { if(id < count - 1) id++; else id = 0; if(((formObject *) LGD(id))->visible) return id; } /* This should not happen */ abort(); return -1; } // Find previous visible object int form::find_prev_visible(int id) { int count = tn_list_size(objDyn); int i = count + 2; while(i--) { if(id) id--; else id = count - 1; if(((formObject *) LGD(id))->visible) return id; } /* This should not happen */ abort(); return -1; } // returns: 0 if failed (escape hit) // otherwise id of button hit int form::run(void) { int i; int count = tn_list_size(objDyn); cursor cs = get_cursor(); bool old_vis = visible; if(!count) return 0; /* No elements in form -> immediate exit */ for(i = 0; i < count; i++) { if(((formObject *) LGD(i))->visible) break; } if(!((formObject *) LGD(i))->visible) assert(0 != 0); visible = true; i = 0; if(remember_id && last_id >= 0 && last_id < count && ((formObject *) LGD(last_id))->visible){ i = last_id; } do { set_cursor(none); draw(); update(); // Handle current item int result = ((formObject *) LGD(i))->getnb(); // Handle its return switch(result) { case -1: i = find_prev_visible(i); break; #if 1 // Radio-tab patch case 2:/* tab (!) WARNING: from radio only (!) */ if(i < count - 1) { i++; radioGroup *rg; formObject *f2; rg = ((radio*) LGD(i-1))->getrgroup(); f2 = (formObject *) LGD(i); if(f2->gettype() == Radio) { while (!((formObject *)LGD(i))->visible || (((formObject *)LGD(i))->gettype() == Radio && rg == ((radio *) LGD(i))->getrgroup())) { if (i < count - 1) { i++; } else { i = 0; break; } } } } break; #else case 2:/* Tab(?) - anyway ... from anywhere :) */ #endif case 1: i = find_next_visible(i); break; case 27: set_cursor(cs); visible = old_vis; return 0; case 0: if (remember_id) last_id = i; int id = ((formObject *) LGD(i))->getid(); if (id) { visible = old_vis; set_cursor(cs); return id; } else { int j; formObject *fo = NULL; for (j = 0; j < tn_list_size(objDyn); j++) { fo = (formObject *) LGD(j); if(fo->gettype() == Button && ((button *)fo)->dflt && fo->visible) { visible = old_vis; set_cursor(cs); return fo->getid(); } } beep(); } } } while(1); } #undef LGD // Change color scheme void form::change_scheme(void) { int i; if (fixed_colors) return; TL = COLOR_FORM_TL; BR = COLOR_FORM_BR; BACKGROUND = COLOR_FORM_BG; for(i = 0; i < tn_list_size(objStatic); i++) { ((formStatic *)tn_list_getdata(objStatic, i))->change_scheme(); } for(i = 0; i < tn_list_size(objDyn); i++) { ((formObject *)tn_list_getdata(objDyn, i))->change_scheme(); } }