'--------------------------------------------------------------------------- ' ' Simple widget set for the high performance canvas - PvE 2016. MIT License. ' Updated May 2018 - PvE 2018 ' '--------------------------------------------------------------------------- ' ' GUI_Background_Color(r, g, b, a) ' => Set the default background color for a widget ' ' GUI_Foreground_Color(r, g, b, a) ' => Set the default foreground color for a widget ' ' GUI_Font_Color(r, g, b, a) ' => Set the default font color for a widget ' ' GUI_Font_Type(path_to_font$) ' => Load a Hershey font to use in the GUI ' ' GUI_Font_Size(scale) ' => Set the font size (default: 0.7) ' ' GUI_Frame(title$, xpos, ypos, xsize, ysize) ' => Create a frame with a caption. If caption is empty a full box is drawn. ' ' GUI_Button(text$, xpos, ypos, xsize, ysize, callback) ' => Create a button with a text at xpos, ypos with size xsize, ysize. Invokes callback function when pressed. ' ' GUI_Check(text$, xpos, ypos, xsize, ysize, callback) ' => Create a check button with a text at xpos, ypos with size xsize, ysize. Invokes callback function when pressed. ' ' GUI_Option(text$, xpos, ypos, xsize, ysize, group$, callback) ' => Create an option button with a text at xpos, ypos with size xsize, ysize. Buttons in the same group exclude each other. Invokes callback function when pressed. ' ' GUI_Label(text$, xpos, ypos) ' => Create a label with a text at xpos, ypos. ' ' GUI_HSlider(xpos, ypos, xsize, ysize, start, end, callback) ' => Create a horizontal slider at xpos, ypos with size xsize, ysize. Values lie in range start-end. Invokes callback function when changed. ' ' GUI_VSlider(xpos, ypos, xsize, ysize, start, end, callback) ' => Create a vertical slider at xpos, ypos with size xsize, ysize. Values lie in range start-end. Invokes callback function when changed. ' ' GUI_List(xpos, ypos, xsize, ysize, callback) ' => Create a list at xpos, ypos with size xsize, ysize. Use 'GUI_Set_String' to populate the list with items. Clear with a empty string. GUI_Get_Property/Set for "value" to get/set row number. Invokes callback when row is activated. ' ' GUI_Text(xpos, ypos, xsize, ysize, callback) ' => Create a multiline textbox at xpos, ypos with size xsize, ysize. Use 'GUI_Set_String' to store text. Clear with a empty string. Invokes callback when clicked. ' ' GUI_HSeparator(xpos, ypos, xsize, ysize) ' => Create a horizontal separator at xpos, ypos with width xsize and height ysize. ' ' GUI_VSeparator(xpos, ypos, xsize, ysize) ' => Create a vertical separator at xpos, ypos with width xsize and height ysize. ' ' GUI_Spin(xpos, ypos, xsize, ysize, start#, end#, step#, callback) ' => Create a spinbutton at xpos, ypos with width xsize and height ysize. Values can vary between start and end. Increased in step. Invokes callback when clicked. ' ' GUI_Get_Property(widgetID, property$) ' => Retrieve value from a property from widget. Property$ can be "status" or "value". ' ' GUI_Set_Property(widgetID, property$, value) ' => Set the value for a property of a widget. Property$ can be "status" or "value". ' ' GUI_Get_String$(widgetID, property$) ' => Retrieve string from a property from widget. Property$ can be "label". ' ' GUI_Set_String(widgetID, property$, text$) ' => Set string for a property of a widget. Property$ can be "label". ' ' GUI_Events ' => Main loop for widget event handling. To be called from a callback function in the canvas program. ' '--------------------------------------------------------------------------- FOR SKIN EDIT HERE ' Define if a skin is used CONST GUI_SKIN = FALSE ' Optionally, include the skinning functions from a separate file 'INCLUDE canvas-plugin-gui-skin.bac '--------------------------------------------------------------------------- NO EDITS STARTING FROM HERE ' Note that the skinning functions should follow the following templates. ' Do not change, GCC needs them for linking. PROTO GUI_Button_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_Frame_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_Check_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_Label_Skin_Draw(long,long,long) TYPE void PROTO GUI_HSlider_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_VSlider_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_Option_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_List_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_Text_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_HSeparator_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_VSeparator_Skin_Draw(long,long,long,long,long) TYPE void PROTO GUI_Spin_Skin_Draw(long,long,long,long,long) TYPE void '--------------------------------------------------------------------------- CONST GUI_FONT_SIZE = 16 : ' CANVAS font size CONST GUI_SLIDER_SIZE = 16 : ' Size of the grip in slider CONST GUI_LIST_MAX = 256 : ' Maximum entries in a list widget RECORD GUI[256] LOCAL type LOCAL label$, group$, previous$ LOCAL callback TYPE void* LOCAL status LOCAL xpos, ypos, xsize, ysize, xblock, yblock, xnew, ynew LOCAL start, end, value, step TYPE double : ' Needed for sliders and spin LOCAL scroll, idx, visible, selected : ' Needed for list LOCAL length : ' Needed for textbox ' vov - need these for font/color control in widgets LOCAL r, g, b, a TYPE unsigned char LOCAL fontsize TYPE float LOCAL bg_r, bg_g, bg_b, bg_a LOCAL fg_r, fg_g, fg_b, fg_a LOCAL font_r, font_g, font_b, font_a LOCAL font_scale TYPE double END RECORD RECORD GUI_PROPERTIES LOCAL widget_ctr LOCAL bg_r, bg_g, bg_b, bg_a LOCAL fg_r, fg_g, fg_b, fg_a LOCAL font_r, font_g, font_b, font_a LOCAL font_scale TYPE double LOCAL str_list$[GUI_LIST_MAX] TYPE STRING LOCAL str_ptr END RECORD CONST GUI_WIDGET_BUTTON = 0 CONST GUI_WIDGET_CHECK = 1 CONST GUI_WIDGET_FRAME = 2 CONST GUI_WIDGET_LABEL = 3 CONST GUI_WIDGET_HSLIDER = 4 CONST GUI_WIDGET_VSLIDER = 5 CONST GUI_WIDGET_OPTION = 6 CONST GUI_WIDGET_LIST = 7 CONST GUI_WIDGET_TEXT = 8 CONST GUI_WIDGET_HSEPARATOR = 9 CONST GUI_WIDGET_VSEPARATOR = 10 CONST GUI_WIDGET_SPIN = 11 ' vov - would like these for extra widgets ' WIDGET_SVG would allow for easy movement of graphics and widget elements CONST GUI_WIDGET_GROUPER = 12 CONST GUI_WIDGET_BAR = 13 CONST GUI_WIDGET_SVG = 14 CONST GUI_STATUS_DISABLED = 0 CONST GUI_STATUS_ENABLED = 1 CONST GUI_STATUS_NORMAL = 2 CONST GUI_STATUS_HOVER = 3 CONST GUI_STATUS_CLICKED = 4 GUI_PROPERTIES.widget_ctr = -1 ' Initialize colors GUI_PROPERTIES.bg_r = 255 GUI_PROPERTIES.bg_g = 255 GUI_PROPERTIES.bg_b = 255 GUI_PROPERTIES.bg_a = 255 GUI_PROPERTIES.fg_r = 64 GUI_PROPERTIES.fg_g = 64 GUI_PROPERTIES.fg_b = 64 GUI_PROPERTIES.fg_a = 255 GUI_PROPERTIES.font_r = 0 GUI_PROPERTIES.font_g = 0 GUI_PROPERTIES.font_b = 0 GUI_PROPERTIES.font_a = 255 GUI_PROPERTIES.font_scale = 0.7 ' Function pointers for skinning interface DECLARE (*GUI_Button_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_Frame_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_Check_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_Label_Draw)(long,long,long) TYPE void DECLARE (*GUI_HSlider_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_VSlider_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_Option_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_List_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_Text_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_HSeparator_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_VSeparator_Draw)(long,long,long,long,long) TYPE void DECLARE (*GUI_Spin_Draw)(long,long,long,long,long) TYPE void ' Set the right functions for widget rendering IF GUI_SKIN = TRUE THEN GUI_Button_Draw = GUI_Button_Skin_Draw GUI_Frame_Draw = GUI_Frame_Skin_Draw GUI_Check_Draw = GUI_Check_Skin_Draw GUI_Label_Draw = GUI_Label_Skin_Draw GUI_HSlider_Draw = GUI_HSlider_Skin_Draw GUI_VSlider_Draw = GUI_VSlider_Skin_Draw GUI_Option_Draw = GUI_Option_Skin_Draw GUI_List_Draw = GUI_List_Skin_Draw GUI_Text_Draw = GUI_Text_Skin_Draw GUI_HSeparator_Draw = GUI_HSeparator_Skin_Draw GUI_VSeparator_Draw = GUI_VSeparator_Skin_Draw GUI_Spin_Draw = GUI_Spin_Skin_Draw ELSE GUI_Button_Draw = GUI_Button_Canvas_Draw GUI_Frame_Draw = GUI_Frame_Canvas_Draw GUI_Check_Draw = GUI_Check_Canvas_Draw GUI_Label_Draw = GUI_Label_Canvas_Draw GUI_HSlider_Draw = GUI_HSlider_Canvas_Draw GUI_VSlider_Draw = GUI_VSlider_Canvas_Draw GUI_Option_Draw = GUI_Option_Canvas_Draw GUI_List_Draw = GUI_List_Canvas_Draw GUI_Text_Draw = GUI_Text_Canvas_Draw GUI_HSeparator_Draw = GUI_HSeparator_Canvas_Draw GUI_VSeparator_Draw = GUI_VSeparator_Canvas_Draw GUI_Spin_Draw = GUI_Spin_Canvas_Draw ENDIF '--------------------------------------------------------------------------- ' Drawing the widgets '--------------------------------------------------------------------------- SUB GUI_Internal_Text(txt$, x, y, wt) LOCAL xpos#, len# SCALE(GUI[wt].font_scale) ' Scaling happens to be around the centre of the text. len# = LEN(txt$)/2*GUI_FONT_SIZE ' Compensate new xposition after scaling xpos# = x- (len# - len#*GUI[wt].font_scale) TEXT(txt$, xpos#, y) ' Restore scaling SCALE(1.0) END SUB SUB GUI_Button_Canvas_Draw(wt, x, y, xsize, ysize) SELECT GUI[wt].status CASE GUI_STATUS_NORMAL INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x+xsize/2-(LEN(GUI[wt].label$)-1)*GUI_FONT_SIZE*GUI[wt].font_scale/2, y+ysize/2, wt) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, FALSE) CASE GUI_STATUS_HOVER INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].fg_a) SQUARE(x+xsize/2+2, y+ysize/2+2, xsize/2+1, ysize/2+1, TRUE) INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x+xsize/2-(LEN(GUI[wt].label$)-1)*GUI_FONT_SIZE*GUI[wt].font_scale/2, y+ysize/2, wt) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b,GUI_PROPERTIES.fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, FALSE) CASE GUI_STATUS_CLICKED INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2+1, ysize/2+1, TRUE) INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x+xsize/2-(LEN(GUI[wt].label$)-1)*GUI_FONT_SIZE*GUI[wt].font_scale/2+2, y+ysize/2+2, wt) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2+2, y+ysize/2+2, xsize/2, ysize/2, FALSE) END SELECT END SUB SUB GUI_Check_Canvas_Draw(wt, x, y, xsize, ysize) IF GUI[wt].status = GUI_STATUS_ENABLED THEN INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+ysize/4, y+ysize/4, ysize/4-3, ysize/4-3, TRUE) ELSE INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) SQUARE(x+ysize/4, y+ysize/4, ysize/4-3, ysize/4-3, TRUE) ENDIF INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+ysize/4, y+ysize/4, ysize/4, ysize/4, FALSE) INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x+ysize/2+GUI_FONT_SIZE, y+ysize/4, wt) END SUB SUB GUI_Frame_Canvas_Draw(wt, x, y, xsize, ysize) IF LEN(GUI[wt].label$) THEN INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) LINE(x, y, x+GUI_FONT_SIZE, y) INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x+2*GUI_FONT_SIZE, y, wt) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) LINE(x+2*GUI_FONT_SIZE+(LEN(GUI[wt].label$)+0.5)*GUI_FONT_SIZE*GUI[wt].font_scale, y, x+xsize, y) ELSE INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) LINE(x, y, x+xsize, y) ENDIF LINE(x+xsize, y, x+xsize, y+ysize) LINE(x+xsize, y+ysize, x, y+ysize) LINE(x, y+ysize, x, y) ENDSUB SUB GUI_Label_Canvas_Draw(wt, x, y) LOCAL len IF LEN(GUI[wt].previous$) THEN len = LEN(GUI[wt].previous$)*GUI_FONT_SIZE*GUI[wt].font_scale INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) SQUARE(x+len/2, y, len/2+8, GUI_FONT_SIZE*GUI[wt].font_scale, TRUE) ENDIF INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x, y, wt) ENDSUB SUB GUI_HSlider_Canvas_Draw(wt, x, y, xsize, ysize) INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) CIRCLE(GUI[wt].xblock, GUI[wt].yblock, GUI_SLIDER_SIZE, GUI_SLIDER_SIZE, TRUE) SELECT GUI[wt].status CASE GUI_STATUS_NORMAL INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) CASE GUI_STATUS_HOVER INK(GUI[wt].fg_r+24, GUI[wt].fg_g+24, GUI[wt].fg_b+24, GUI[wt].fg_a) CASE GUI_STATUS_CLICKED INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) END SELECT LINE(x, y, x+xsize, y) LINE(x+xsize, y, x+xsize, y+ysize) LINE(x+xsize, y+ysize, x, y+ysize) LINE(x, y+ysize, x, y) CIRCLE(GUI[wt].xnew, GUI[wt].yblock, GUI_SLIDER_SIZE, GUI_SLIDER_SIZE, TRUE) GUI[wt].xblock = GUI[wt].xnew ENDSUB SUB GUI_VSlider_Canvas_Draw(wt, x, y, xsize, ysize) INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) CIRCLE(GUI[wt].xblock, GUI[wt].yblock, GUI_SLIDER_SIZE, GUI_SLIDER_SIZE, TRUE) SELECT GUI[wt].status CASE GUI_STATUS_NORMAL INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) CASE GUI_STATUS_HOVER INK(GUI[wt].fg_r+24, GUI[wt].fg_g+24, GUI[wt].fg_b+24, GUI[wt].fg_a) CASE GUI_STATUS_CLICKED INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) END SELECT LINE(x, y, x+xsize, y) LINE(x+xsize, y, x+xsize, y+ysize) LINE(x+xsize, y+ysize, x, y+ysize) LINE(x, y+ysize, x, y) CIRCLE(GUI[wt].xblock, GUI[wt].ynew, GUI_SLIDER_SIZE, GUI_SLIDER_SIZE, TRUE) GUI[wt].yblock = GUI[wt].ynew ENDSUB SUB GUI_Option_Canvas_Draw(wt, x, y, xsize, ysize) IF GUI[wt].status = GUI_STATUS_ENABLED THEN INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) CIRCLE(x+ysize/4, y+ysize/4, ysize/4-3, ysize/4-3, TRUE) ELSE INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) CIRCLE(x+ysize/4, y+ysize/4, ysize/4-3, ysize/4-3, TRUE) ENDIF INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) CIRCLE(x+ysize/4, y+ysize/4, ysize/4, ysize/4, FALSE) INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(GUI[wt].label$, x+ysize/2+GUI_FONT_SIZE, y+ysize/4, wt) END SUB SUB GUI_List_Canvas_Draw(wt, x, y, xsize, ysize) LOCAL i, len, showbar INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, TRUE) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, FALSE) IF GUI_PROPERTIES.str_ptr > 0 THEN GUI[wt].visible = 0 ' How many characters fit in one line. Line starts with 1 char offset. len = xsize/(GUI_FONT_SIZE*GUI[wt].font_scale)-1 ' Draw text and count visible lines FOR i = 0 TO GUI_PROPERTIES.str_ptr-1 IF y+GUI_FONT_SIZE+i*1.5*GUI_FONT_SIZE < y+ysize THEN IF i + 1 = GUI[wt].selected THEN INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, 128) SQUARE(x+xsize/2, y+GUI_FONT_SIZE+i*1.5*GUI_FONT_SIZE, xsize/2, GUI_FONT_SIZE-2, TRUE) ENDIF INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(LEFT$(GUI_PROPERTIES.str_list$[GUI[wt].idx+i], len), x+GUI_FONT_SIZE, y+GUI_FONT_SIZE+i*1.5*GUI_FONT_SIZE, wt) INCR GUI[wt].visible ELSE showbar = TRUE ENDIF NEXT ENDIF IF showbar THEN IF GUI[wt].scroll = 1 THEN INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, TRUE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, FALSE) ROTATION(0) ELIF GUI[wt].scroll = 2 THEN INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, FALSE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, TRUE) ROTATION(0) ELSE INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, TRUE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, TRUE) ROTATION(0) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, FALSE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, FALSE) ROTATION(0) ENDIF ENDIF END SUB SUB GUI_Text_Canvas_Draw(wt, x, y, xsize, ysize) LOCAL showbar, start, tlen, row INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, TRUE) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, FALSE) IF LEN(GUI[wt].label$) > 0 THEN GUI[wt].visible = 0 ' From which position to show start = GUI[wt].idx WHILE NOT(REGEX(MID$(GUI[wt].label$, start, 1), "[[:blank:]]")) AND start > 1 DECR start WEND ' Draw text and count visible lines INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) WHILE start <= LEN(GUI[wt].label$) tlen = IIF(start + GUI[wt].length <= LEN(GUI[wt].label$), GUI[wt].length, LEN(GUI[wt].label$) ) ' Check if we did not exceed box vertically IF y+GUI_FONT_SIZE+row*1.5*GUI_FONT_SIZE < y+ysize THEN IF tlen = GUI[wt].length THEN WHILE NOT(REGEX(MID$(GUI[wt].label$, start+tlen, 1), "[[:blank:]]")) AND tlen > 0 DECR tlen WEND IF tlen = 0 THEN WHILE NOT(REGEX(MID$(GUI[wt].label$, start+tlen, 1), "[[:blank:]]")) AND tlen < GUI[wt].length INCR tlen WEND ENDIF ENDIF GUI_Internal_Text(CHOP$(MID$(GUI[wt].label$, start, tlen)), x+GUI_FONT_SIZE/2, y+GUI_FONT_SIZE+row*1.5*GUI_FONT_SIZE, wt) INCR GUI[wt].visible INCR start, tlen INCR row ELSE showbar = TRUE BREAK ENDIF WEND ENDIF IF showbar OR GUI[wt].idx > 1 THEN IF GUI[wt].scroll = 1 THEN INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, TRUE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, FALSE) ROTATION(0) ELIF GUI[wt].scroll = 2 THEN INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, FALSE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, TRUE) ROTATION(0) ELSE INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, TRUE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, TRUE) ROTATION(0) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, FALSE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, FALSE) ROTATION(0) ENDIF ENDIF END SUB SUB GUI_HSeparator_Canvas_Draw(wt, x, y, xsize, ysize) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, TRUE) END SUB SUB GUI_VSeparator_Canvas_Draw(wt, x, y, xsize, ysize) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, TRUE) END SUB SUB GUI_Spin_Canvas_Draw(wt, x, y, xsize, ysize) LOCAL len INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, TRUE) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) SQUARE(x+xsize/2, y+ysize/2, xsize/2, ysize/2, FALSE) ' How many characters fit in one line. Line starts with 1 char offset. len = xsize/(GUI_FONT_SIZE*GUI[wt].font_scale)-1 ' Draw value IF y+GUI_FONT_SIZE < y+ysize THEN INK(GUI[wt].font_r, GUI[wt].font_g, GUI[wt].font_b, GUI[wt].font_a) GUI_Internal_Text(LEFT$(STR$(GUI[wt].value), len), x+GUI_FONT_SIZE, y+GUI_FONT_SIZE, wt) ENDIF IF GUI[wt].scroll = 1 THEN INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, TRUE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, FALSE) ROTATION(0) ELIF GUI[wt].scroll = 2 THEN INK(GUI[wt].fg_r+64, GUI[wt].fg_g+64, GUI[wt].fg_b+64, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, FALSE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, TRUE) ROTATION(0) ELSE INK(GUI[wt].bg_r, GUI[wt].bg_g, GUI[wt].bg_b, GUI[wt].bg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, TRUE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, TRUE) ROTATION(0) INK(GUI[wt].fg_r, GUI[wt].fg_g, GUI[wt].fg_b, GUI[wt].fg_a) TRIANGLE(x+xsize-9, y+ysize/4, 12, ysize/2-2, FALSE) ROTATION(180) TRIANGLE(x+xsize-9, y+ysize-ysize/4, 12, ysize/2-2, FALSE) ROTATION(0) ENDIF END SUB '--------------------------------------------------------------------------- ' Registering the widgets (API) '--------------------------------------------------------------------------- FUNCTION GUI_Button(txt$, x, y, xsize, ysize, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_BUTTON GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].label$ = txt$ GUI[id].status = GUI_STATUS_NORMAL GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Check(txt$, x, y, xsize, ysize, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_CHECK GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].label$ = txt$ GUI[id].status = GUI_STATUS_DISABLED GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Option(txt$, x, y, xsize, ysize, group$, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_OPTION GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].label$ = txt$ GUI[id].group$ = group$ GUI[id].status = GUI_STATUS_DISABLED GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Frame(txt$, x, y, xsize, ysize) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_FRAME GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].label$ = txt$ GUI[id].callback = NULL GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Label(txt$, x, y) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_LABEL GUI[id].xpos = x GUI[id].ypos = y GUI[id].label$ = txt$ GUI[id].callback = NULL GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_HSlider(x, y, xsize, ysize, start, end, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_HSLIDER GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].xblock = x GUI[id].yblock = y+ysize/2 GUI[id].xnew = x GUI[id].value = 0 GUI[id].start = start GUI[id].end = end GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_VSlider(x, y, xsize, ysize, start, end, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_VSLIDER GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].xblock = x+xsize/2 GUI[id].yblock = y GUI[id].ynew = y GUI[id].value = 0 GUI[id].start = start GUI[id].end = end GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_List(x, y, xsize, ysize, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_LIST GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Text(x, y, xsize, ysize, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_TEXT GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].callback = cb GUI[id].length = xsize/(GUI_FONT_SIZE*GUI_PROPERTIES.font_scale)-1 GUI[id].idx = 1 GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_HSeparator(x, y, xsize, ysize) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_HSEPARATOR GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_VSeparator(x, y, xsize, ysize) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_VSEPARATOR GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Spin(x, y, xsize, ysize, start#, end#, step#, void* cb) LOCAL id INCR GUI_PROPERTIES.widget_ctr id = GUI_PROPERTIES.widget_ctr GUI[id].type = GUI_WIDGET_SPIN GUI[id].xpos = x GUI[id].ypos = y GUI[id].xsize = xsize GUI[id].ysize = ysize GUI[id].start = start# GUI[id].value = start# GUI[id].end = end# GUI[id].step = step# GUI[id].callback = cb GUI[id].bg_r = GUI_PROPERTIES.bg_r GUI[id].bg_g = GUI_PROPERTIES.bg_g GUI[id].bg_b = GUI_PROPERTIES.bg_b GUI[id].bg_a = GUI_PROPERTIES.bg_a GUI[id].fg_r = GUI_PROPERTIES.fg_r GUI[id].fg_g = GUI_PROPERTIES.fg_g GUI[id].fg_b = GUI_PROPERTIES.fg_b GUI[id].fg_a = GUI_PROPERTIES.fg_a GUI[id].font_r = GUI_PROPERTIES.font_r GUI[id].font_g = GUI_PROPERTIES.font_g GUI[id].font_b = GUI_PROPERTIES.font_b GUI[id].font_a = GUI_PROPERTIES.font_a GUI[id].font_scale = GUI_PROPERTIES.font_scale RETURN id END FUNCTION FUNCTION GUI_Get_Property(wt, prop$) LOCAL property TYPE double SELECT prop$ CASE "status" property = GUI[wt].status CASE "value" IF GUI[wt].type = GUI_WIDGET_LIST THEN GUI[wt].value = GUI[wt].idx + GUI[wt].selected property = GUI[wt].value ENDSELECT RETURN property END FUNCTION FUNCTION GUI_Get_String$(wt, prop$) LOCAL property$ SELECT prop$ CASE "label" property$ = GUI[wt].label$ ENDSELECT RETURN property$ END FUNCTION SUB GUI_Set_Property(wt, prop$, value) SELECT prop$ CASE "status" GUI[wt].status = value CASE "value" SELECT GUI[wt].type CASE GUI_WIDGET_HSLIDER GUI[wt].xnew = GUI[wt].xpos + value/(GUI[wt].end-GUI[wt].start)*GUI[wt].xsize GUI[wt].value = value CASE GUI_WIDGET_VSLIDER GUI[wt].ynew = GUI[wt].ypos + value/(GUI[wt].end-GUI[wt].start)*GUI[wt].ysize GUI[wt].value = value CASE GUI_WIDGET_LIST IF value > 0 AND value <= GUI_PROPERTIES.str_ptr THEN GUI[wt].selected = value - GUI[wt].idx GUI[wt].label$ = GUI_PROPERTIES.str_list$[GUI[wt].idx+GUI[wt].selected - 1] GUI[wt].value = value ENDIF DEFAULT GUI[wt].value = value ENDSELECT ENDSELECT END SUB SUB GUI_Set_String(wt, prop$, str$) LOCAL i SELECT prop$ CASE "label" IF GUI[wt].type = GUI_WIDGET_LIST THEN IF LEN(str$) THEN IF GUI_PROPERTIES.str_ptr < GUI_LIST_MAX THEN GUI_PROPERTIES.str_list$[GUI_PROPERTIES.str_ptr] = str$ INCR GUI_PROPERTIES.str_ptr ENDIF ELSE FOR i = 0 TO GUI_PROPERTIES.str_ptr-1 GUI_PROPERTIES.str_list$[i] = "" NEXT GUI_PROPERTIES.str_ptr = 0 GUI[wt].idx = 0 GUI[wt].selected = 0 GUI[wt].label$ = "" GUI[wt].value = 0 ENDIF ELSE GUI[wt].previous$ = GUI[wt].label$ GUI[wt].label$ = str$ ENDIF ENDSELECT END SUB SUB GUI_Background_Color(r, g, b, a) GUI_PROPERTIES.bg_r = IIF(r > 255, 255, r) GUI_PROPERTIES.bg_g = IIF(g > 255, 255, g) GUI_PROPERTIES.bg_b = IIF(b > 255, 255, b) GUI_PROPERTIES.bg_a = IIF(a > 255, 255, a) END SUB SUB GUI_Foreground_Color(r, g, b, a) GUI_PROPERTIES.fg_r = IIF(r > 255, 255, r) GUI_PROPERTIES.fg_g = IIF(g > 255, 255, g) GUI_PROPERTIES.fg_b = IIF(b > 255, 255, b) GUI_PROPERTIES.fg_a = IIF(a > 255, 255, a) END SUB SUB GUI_Font_Color(r, g, b, a) GUI_PROPERTIES.font_r = IIF(r > 255, 255, r) GUI_PROPERTIES.font_g = IIF(g > 255, 255, g) GUI_PROPERTIES.font_b = IIF(b > 255, 255, b) GUI_PROPERTIES.font_a = IIF(a > 255, 255, a) END SUB SUB GUI_Font_Type(font$) LOADFONT(font$) END SUB SUB GUI_Font_Size(scale#) GUI_PROPERTIES.font_scale = scale# END SUB '--------------------------------------------------------------------------- ' Handling events from mouse click, and handle rendering '--------------------------------------------------------------------------- SUB GUI_Events LOCAL amount, size, idx, xpos, ypos, mb, op LOCAL (*func)(int) TYPE void LOCAL mb_stat = 0 TYPE static int xpos = MOUSE(0) ypos = MOUSE(1) mb = MOUSE(2) IF GUI_PROPERTIES.widget_ctr < 0 THEN EXIT ' Determine current status and draw widgets FOR idx = 0 TO GUI_PROPERTIES.widget_ctr ' Status based on mouse click or drag SELECT GUI[idx].type CASE GUI_WIDGET_BUTTON IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos+GUI[idx].xsize AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize THEN IF mb = 1 THEN IF mb_stat = 0 THEN IF GUI[idx].status = GUI_STATUS_NORMAL OR GUI[idx].status = GUI_STATUS_HOVER THEN GUI[idx].status = GUI_STATUS_CLICKED IF GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF ELSE GUI[idx].status = GUI_STATUS_NORMAL ENDIF ENDIF ELSE GUI[idx].status = GUI_STATUS_HOVER ENDIF ELSE GUI[idx].status = GUI_STATUS_NORMAL ENDIF CASE GUI_WIDGET_CHECK IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos+GUI[idx].xsize AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize THEN IF mb = 1 THEN IF mb_stat = 0 THEN IF GUI[idx].status = GUI_STATUS_DISABLED THEN GUI[idx].status = GUI_STATUS_ENABLED IF GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF ELSE GUI[idx].status = GUI_STATUS_DISABLED ENDIF ENDIF ENDIF ENDIF CASE GUI_WIDGET_HSLIDER IF xpos > GUI[idx].xblock-GUI_SLIDER_SIZE AND xpos < GUI[idx].xblock+GUI_SLIDER_SIZE AND ypos > GUI[idx].yblock-GUI_SLIDER_SIZE AND ypos < GUI[idx].yblock+GUI_SLIDER_SIZE THEN IF mb = 1 THEN IF xpos <= GUI[idx].xpos+GUI[idx].xsize AND xpos >= GUI[idx].xpos THEN GUI[idx].xnew = xpos GUI[idx].value = INT((xpos-GUI[idx].xpos)/GUI[idx].xsize*(GUI[idx].end-GUI[idx].start)) ENDIF IF GUI[idx].xnew <> GUI[idx].xblock AND GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF IF mb_stat = 0 THEN IF GUI[idx].status = GUI_STATUS_NORMAL OR GUI[idx].status = GUI_STATUS_HOVER THEN GUI[idx].status = GUI_STATUS_CLICKED ELSE GUI[idx].status = GUI_STATUS_NORMAL ENDIF ENDIF ELSE GUI[idx].status = GUI_STATUS_HOVER ENDIF ELSE GUI[idx].status = GUI_STATUS_NORMAL ENDIF CASE GUI_WIDGET_VSLIDER IF xpos > GUI[idx].xblock-GUI_SLIDER_SIZE AND xpos < GUI[idx].xblock+GUI_SLIDER_SIZE AND ypos > GUI[idx].yblock-GUI_SLIDER_SIZE AND ypos < GUI[idx].yblock+GUI_SLIDER_SIZE THEN IF mb = 1 THEN IF ypos <= GUI[idx].ypos+GUI[idx].ysize AND ypos >= GUI[idx].ypos THEN GUI[idx].ynew = ypos GUI[idx].value = INT((ypos-GUI[idx].ypos)/GUI[idx].ysize*(GUI[idx].end-GUI[idx].start)) ENDIF IF GUI[idx].ynew <> GUI[idx].yblock AND GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF IF mb_stat = 0 THEN IF GUI[idx].status = GUI_STATUS_NORMAL OR GUI[idx].status = GUI_STATUS_HOVER THEN GUI[idx].status = GUI_STATUS_CLICKED ELSE GUI[idx].status = GUI_STATUS_NORMAL ENDIF ENDIF ELSE GUI[idx].status = GUI_STATUS_HOVER ENDIF ELSE GUI[idx].status = GUI_STATUS_NORMAL ENDIF CASE GUI_WIDGET_OPTION IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos+GUI[idx].xsize AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize/2 THEN IF mb = 1 THEN IF mb_stat = 0 THEN IF GUI[idx].status = GUI_STATUS_DISABLED THEN GUI[idx].status = GUI_STATUS_ENABLED FOR op = 0 TO GUI_PROPERTIES.widget_ctr IF GUI[op].type = GUI_WIDGET_OPTION AND op <> idx AND EQUAL(GUI[idx].group$, GUI[op].group$) THEN GUI[op].status = GUI_STATUS_DISABLED ENDIF NEXT IF GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF ELSE GUI[idx].status = GUI_STATUS_DISABLED ENDIF ENDIF ENDIF ENDIF CASE GUI_WIDGET_LIST IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos+GUI[idx].xsize AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize THEN IF mb = 1 THEN IF mb_stat = 0 THEN ' Control scrolling IF xpos > GUI[idx].xpos + GUI[idx].xsize-16 AND ypos < GUI[idx].ypos+GUI[idx].ysize/2 THEN GUI[idx].scroll = 1 IF GUI[idx].idx > 0 THEN DECR GUI[idx].idx INCR GUI[idx].selected ENDIF ELIF xpos > GUI[idx].xpos + GUI[idx].xsize-16 AND ypos > GUI[idx].ypos+GUI[idx].ysize/2 THEN GUI[idx].scroll = 2 IF GUI[idx].idx + GUI[idx].visible < GUI_PROPERTIES.str_ptr THEN INCR GUI[idx].idx DECR GUI[idx].selected ENDIF ELSE GUI[idx].scroll = 0 ENDIF ' Control selection IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos + GUI[idx].xsize-16 AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize THEN GUI[idx].selected = (ypos-GUI[idx].ypos) / (1.5*GUI_FONT_SIZE) + 1 GUI[idx].label$ = GUI_PROPERTIES.str_list$[GUI[idx].idx+GUI[idx].selected - 1] ENDIF ' Callback IF GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF ELSE mb = 0 ENDIF ELSE GUI[idx].scroll = 0 ENDIF ENDIF CASE GUI_WIDGET_TEXT IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos+GUI[idx].xsize AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize THEN IF mb = 1 THEN IF mb_stat = 0 THEN ' Control scrolling IF xpos > GUI[idx].xpos + GUI[idx].xsize-16 AND ypos < GUI[idx].ypos+GUI[idx].ysize/2 THEN GUI[idx].scroll = 1 IF GUI[idx].idx > GUI[idx].length THEN DECR GUI[idx].idx, GUI[idx].length ENDIF ELIF xpos > GUI[idx].xpos + GUI[idx].xsize-16 AND ypos > GUI[idx].ypos+GUI[idx].ysize/2 THEN GUI[idx].scroll = 2 IF GUI[idx].idx < LEN(GUI[idx].label$)-GUI[idx].length THEN INCR GUI[idx].idx, GUI[idx].length ENDIF ELSE GUI[idx].scroll = 0 ENDIF ' Callback IF GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF ELSE mb = 0 ENDIF ELSE GUI[idx].scroll = 0 ENDIF ENDIF CASE GUI_WIDGET_SPIN IF xpos > GUI[idx].xpos AND xpos < GUI[idx].xpos+GUI[idx].xsize AND ypos > GUI[idx].ypos AND ypos < GUI[idx].ypos+GUI[idx].ysize THEN IF mb = 1 THEN IF mb_stat = 0 THEN ' Control scrolling IF xpos > GUI[idx].xpos + GUI[idx].xsize-16 AND ypos < GUI[idx].ypos+GUI[idx].ysize/2 THEN GUI[idx].scroll = 1 IF GUI[idx].value < GUI[idx].end THEN INCR GUI[idx].value, GUI[idx].step ENDIF ELIF xpos > GUI[idx].xpos + GUI[idx].xsize-16 AND ypos > GUI[idx].ypos+GUI[idx].ysize/2 THEN GUI[idx].scroll = 2 IF GUI[idx].value > GUI[idx].start THEN DECR GUI[idx].value, GUI[idx].step ENDIF ELSE GUI[idx].scroll = 0 ENDIF ' Check value boundary IF GUI[idx].value < GUI[idx].start THEN GUI[idx].value = GUI[idx].start IF GUI[idx].value > GUI[idx].end THEN GUI[idx].value = GUI[idx].end ' Callback IF GUI[idx].callback <> NULL THEN func = GUI[idx].callback CALL (*func)(idx) ENDIF ELSE mb = 0 ENDIF ELSE GUI[idx].scroll = 0 ENDIF ENDIF ENDSELECT ' Render all widgets, we pass coordinates explicitly to keep code simple SELECT GUI[idx].type CASE GUI_WIDGET_BUTTON CALL (*GUI_Button_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_FRAME CALL (*GUI_Frame_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_CHECK CALL (*GUI_Check_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_LABEL CALL (*GUI_Label_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos) CASE GUI_WIDGET_HSLIDER CALL (*GUI_HSlider_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_VSLIDER CALL (*GUI_VSlider_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_OPTION CALL (*GUI_Option_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_LIST CALL (*GUI_List_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_TEXT CALL (*GUI_Text_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_HSEPARATOR CALL (*GUI_HSeparator_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_VSEPARATOR CALL (*GUI_VSeparator_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) CASE GUI_WIDGET_SPIN CALL (*GUI_Spin_Draw)(idx, GUI[idx].xpos, GUI[idx].ypos, GUI[idx].xsize, GUI[idx].ysize) ENDSELECT NEXT ' Save mouse button status mb_stat = mb END SUB '---------------------------------------------------------------------------