www.pudn.com > map_editor.rar > elwindows.c
#include#include #include "global.h" #include "elwindows.h" windows_info windows_list; // the master list of windows /* * The intent of the windows system is to create the window once * and then hide the window when you don't wantto use it. * * Window #0 is special ... it represents the entire screen * * Note: In the handlers, all cursor coordinates are relative to the window * */ // general windows manager functions void display_windows(int level) { int id; int next_id; int i; windows_list.display_level= level; glColor3f(1.0f, 1.0f, 1.0f); // first draw everything that is last under everything id= -1; while(1) { next_id= -9999; for(i=1; i 0){ // at this level? if(windows_list.window[i].order == id){ display_window(i); } else if(windows_list.window[i].order < id && windows_list.window[i].order > next_id){ // try to find the next level next_id= windows_list.window[i].order; } } } if(next_id <= -9999) { break; } else { id= next_id; } } if(level > 0) { // now display each window in the proper order id= 1; while(1) { next_id= 9999; for(i=1; i 0){ // at this level? if(windows_list.window[i].order == id){ display_window(i); } else if(windows_list.window[i].order > id && windows_list.window[i].order < next_id){ // try to find the next level next_id= windows_list.window[i].order; } } } if(next_id >= 9999) { break; } else { id= next_id; } } } } int click_in_windows(int _x, int _y, Uint32 flags) { int done= 0; int id; int next_id; int first_win= 0; int i; // watch for needing to convert the globals into the flags if(!flags){ if(shift_on) flags |= ELW_SHIFT; if(ctrl_on) flags |= ELW_CTRL; if(alt_on) flags |= ELW_ALT; if(right_click) flags |= ELW_RIGHT_MOUSE; if(middle_click) flags |= ELW_MID_MOUSE; if(left_click) flags |= ELW_LEFT_MOUSE; // TODO: centralized double click handling // TODO: consider other ways of triggering double clieck, like middle click or shift click //if(double_click) flags |= ELW_DBL_CLICK; } // check each window in the proper order if(windows_list.display_level > 0) { id= 9999; while(done <= 0) { next_id= 0; for(i=1; i 0){ // at this level? if(windows_list.window[i].order == id){ done= click_in_window(i, _x, _y, flags); if(done > 0){ if(windows_list.window[i].displayed > 0) select_window(i); // select this window to the front return i; } if(first_win == 0 && mouse_in_window(i, _x, _y)) first_win= i; } else if(windows_list.window[i].order < id && windows_list.window[i].order > next_id){ // try to find the next level next_id= windows_list.window[i].order; } } } if(next_id <= 0) { break; } else { id= next_id; } } } // now check the background windows in the proper order id= -9999; while(done <= 0) { next_id= 0; for(i=1; i 0){ // at this level? if(windows_list.window[i].order == id){ done= click_in_window(i, _x, _y, flags); if(done > 0){ //select_window(i); // these never get selected return i; } } else if(windows_list.window[i].order > id && windows_list.window[i].order < next_id){ // try to find the next level next_id= windows_list.window[i].order; } } } if(next_id >= 0) { break; } else { id= next_id; } } // nothing to click on, do a select instead if(first_win > 0) { select_window(first_win); return 1; } return 0; // no click in a window } int drag_windows(int _x, int _y, int dx, int dy) { int next_id; int id, i; int drag_id= 0; // check each window in the proper order for which one might be getting dragged if(windows_list.display_level > 0) { id= 9999; while(drag_id <= 0) { next_id= 0; for(i=1; i 0 && (windows_list.window[i].flags&ELW_DRAGGABLE)){ // at this level? if(windows_list.window[i].order == id){ // check for being actively dragging or on the top bar if(windows_list.window[i].dragged || (mouse_in_window(i, _x, _y) && _y next_id){ // try to find the next level next_id= windows_list.window[i].order; } } } if(next_id <= 0) { break; } else { id= next_id; } } } // this section probably won't be needed, included to be complete // now check the background windows in the proper order for which one might be getting dragged id= -9999; while(drag_id <= 0) { next_id= 0; for(i=1; i 0 && (windows_list.window[i].flags&ELW_DRAGGABLE)){ // at this level? if(windows_list.window[i].order == id){ // check for being actively dragging or on the top bar if(windows_list.window[i].dragged || (mouse_in_window(i, _x, _y) && _y id && windows_list.window[i].order < next_id){ // try to find the next level next_id= windows_list.window[i].order; } } } if(next_id >= 0) { break; } else { id= next_id; } } // are we dragging a window? if(drag_id <= 0) return 0; // dragged window is always on top select_window(drag_id); // flag we are dragging windows_list.window[drag_id].dragged= 1; if(left_click>1 && (dx != 0 || dy != 0)) // TODO: avoid globals? { // move to new location move_window(drag_id, windows_list.window[drag_id].pos_id, windows_list.window[drag_id].pos_loc, windows_list.window[drag_id].pos_x+dx, windows_list.window[drag_id].pos_y+dy); } return 1; } void end_drag_windows() { int i; for(i= 0; i = windows_list.num_windows) return -1; if(windows_list.window[win_id].window_id != win_id) return -1; // shuffle the order of the windows old= windows_list.window[win_id].order; if(old <= 0) return 0; // show last are never shuffled for(i=1; i old){ windows_list.window[i].order--; } } // and put it on top windows_list.window[win_id].order= windows_list.num_windows-1; return 1; } // specific windows functions int create_window(const char *name, int pos_id, Uint32 pos_loc, int pos_x, int pos_y, int size_x, int size_y, Uint32 property_flags) { int win_id=-1; int i; // verify that we are setup and space allocated if(!windows_list.window) { // allocate the space windows_list.num_windows= 0; windows_list.max_windows= 32; windows_list.window=(window_info *)calloc(32, sizeof(window_info)); windows_list.window[0].window_id= -1; // force a rebuild of this windows_list.num_windows= 1; } // now, verify that the main window is correct if(windows_list.window[0].window_id != 0 || windows_list.window[0].len_x != window_width) { // this window is currently here only to help position things // this represents the entire screen windows_list.window[0].window_id= 0; windows_list.window[0].order= -1; windows_list.window[0].pos_id= -1; windows_list.window[0].pos_loc= 0; windows_list.window[0].pos_x= 0; windows_list.window[0].pos_y= 0; windows_list.window[0].len_x= window_width; windows_list.window[0].len_y= window_height; windows_list.window[0].cur_x= 0; windows_list.window[0].cur_y= 0; windows_list.window[0].flags=0; windows_list.window[0].displayed=0; } // find an empty slot for(i=1; i 0) { windows_list.window[win_id].window_id= win_id; windows_list.window[win_id].order= (property_flags&ELW_SHOW_LAST)?-win_id:win_id; windows_list.window[win_id].flags= property_flags; windows_list.window[win_id].displayed= (property_flags&ELW_SHOW)?1:0; //windows_list.window[win_id].collapsed= 0; windows_list.window[win_id].dragged= 0; strncpy(windows_list.window[win_id].window_name, name, 32); windows_list.window[win_id].back_color[0]= 0.0f; windows_list.window[win_id].back_color[1]= 0.0f; windows_list.window[win_id].back_color[2]= 0.0f; windows_list.window[win_id].back_color[3]= 0.5f; windows_list.window[win_id].border_color[0]= 0.77f; windows_list.window[win_id].border_color[1]= 0.57f; windows_list.window[win_id].border_color[2]= 0.39f; windows_list.window[win_id].border_color[3]= 0.0f; windows_list.window[win_id].line_color[0]= 0.77f; windows_list.window[win_id].line_color[1]= 0.57f; windows_list.window[win_id].line_color[2]= 0.39f; windows_list.window[win_id].line_color[3]= 0.0f; windows_list.window[win_id].init_handler= NULL; windows_list.window[win_id].display_handler= NULL; windows_list.window[win_id].click_handler= NULL; windows_list.window[win_id].mouseover_handler= NULL; init_window(win_id, pos_id, pos_loc, pos_x, pos_y, size_x, size_y); } return win_id; } void destroy_window(int win_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return; if(windows_list.window[win_id].window_id != win_id) return; // mark the window as unused windows_list.window[win_id].window_id= -1; windows_list.window[win_id].order= -1; windows_list.window[win_id].displayed= 0; } int init_window(int win_id, int pos_id, Uint32 pos_loc, int pos_x, int pos_y, int size_x, int size_y) { if(win_id <=0 || win_id >= windows_list.num_windows) return -1; if(windows_list.window[win_id].window_id != win_id) return -1; move_window(win_id, pos_id, pos_loc, pos_x, pos_y); windows_list.window[win_id].len_x= size_x; windows_list.window[win_id].len_y= size_y; if(windows_list.window[win_id].init_handler) { return((*windows_list.window[win_id].init_handler)(&windows_list.window[win_id])); } return 1; } int move_window(int win_id, int pos_id, Uint32 pos_loc, int pos_x, int pos_y) { if(win_id <=0 || win_id >= windows_list.num_windows) return -1; if(windows_list.window[win_id].window_id != win_id) return -1; windows_list.window[win_id].pos_id= pos_id; //NOT SUPPORTED YET windows_list.window[win_id].pos_loc= pos_loc; //NOT SUPPORTED YET windows_list.window[win_id].pos_x= pos_x; windows_list.window[win_id].pos_y= pos_y; windows_list.window[win_id].cur_x= pos_x; windows_list.window[win_id].cur_y= pos_y; return 1; } int draw_window_title(window_info *win) { float u_first_start= (float)31/255; float u_first_end= 0; float v_first_start= 1.0f-(float)160/255; float v_first_end= 1.0f-(float)175/255; float u_middle_start= (float)32/255; float u_middle_end= (float)63/255; float v_middle_start= 1.0f-(float)160/255; float v_middle_end= 1.0f-(float)175/255; float u_last_start= 0; float u_last_end= (float)31/255; float v_last_start= 1.0f-(float)160/255; float v_last_end= 1.0f-(float)175/255; if((win->flags&ELW_TITLE_BAR) == ELW_TITLE_NONE) return 0; glColor3f(1.0f,1.0f,1.0f); //ok, now draw that shit... get_and_set_texture_id(icons_text); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER,0.03f); glBegin(GL_QUADS); glTexCoord2f(u_first_end, v_first_start); glVertex3i(0, -ELW_TITLE_HEIGHT, 0); glTexCoord2f(u_first_end, v_first_end); glVertex3i(0, 0, 0); glTexCoord2f(u_first_start, v_first_end); glVertex3i(32, 0, 0); glTexCoord2f(u_first_start, v_first_start); glVertex3i(32, -ELW_TITLE_HEIGHT, 0); // draw one streched out cell to the proper size glTexCoord2f(u_middle_end, v_middle_start); glVertex3i(32, -ELW_TITLE_HEIGHT, 0); glTexCoord2f(u_middle_end, v_middle_end); glVertex3i(32, 0, 0); glTexCoord2f(u_middle_start, v_middle_end); glVertex3i(win->len_x-32, 0, 0); glTexCoord2f(u_middle_start, v_middle_start); glVertex3i(win->len_x-32, -ELW_TITLE_HEIGHT, 0); glTexCoord2f(u_last_end, v_last_start); glVertex3i(win->len_x-32, -ELW_TITLE_HEIGHT, 0); glTexCoord2f(u_last_end, v_last_end); glVertex3i(win->len_x-32, 0, 0); glTexCoord2f(u_last_start, v_last_end); glVertex3i(win->len_x, 0, 0); glTexCoord2f(u_last_start, v_last_start); glVertex3i(win->len_x, -ELW_TITLE_HEIGHT, 0); glEnd(); glDisable(GL_ALPHA_TEST); // draw the name of the window if(win->flags&ELW_TITLE_NAME) { int len; const unsigned char* name = (const unsigned char*) win->window_name; glEnable(GL_TEXTURE_2D); glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]); // center text len = (get_string_width (name) * 8) / 12; draw_string_small((win->len_x-len)/2, -ELW_TITLE_HEIGHT, name, 1); } return 1; } int draw_window_border(window_info *win) { if(win->flags&ELW_USE_BACKGROUND) { glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_SRC_ALPHA); glColor4f(win->back_color[0],win->back_color[1],win->back_color[2],win->back_color[3]); glBegin(GL_QUADS); glVertex3i(0, win->len_y, 0); glVertex3i(0, 0, 0); glVertex3i(win->len_x, 0, 0); glVertex3i(win->len_x, win->len_y, 0); glEnd(); glDisable(GL_BLEND); } if(win->flags&ELW_USE_BORDER) { glDisable(GL_TEXTURE_2D); glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]); glBegin(GL_LINES); glVertex3i(0, 0, 0); glVertex3i(win->len_x, 0, 0); glVertex3i(win->len_x, 0, 0); glVertex3i(win->len_x, win->len_y, 0); glVertex3i(win->len_x, win->len_y, 0); glVertex3i(0, win->len_y, 0); glVertex3i(0, win->len_y, 0); glVertex3i(0, 0, 0); } if(win->flags&ELW_CLOSE_BOX) { //draw the corner, with the X in glColor3f(win->border_color[0],win->border_color[1],win->border_color[2]); glBegin(GL_LINES); glVertex3i(win->len_x, ELW_BOX_SIZE, 0); glVertex3i(win->len_x-ELW_BOX_SIZE, ELW_BOX_SIZE, 0); glVertex3i(win->len_x-ELW_BOX_SIZE, ELW_BOX_SIZE, 0); glVertex3i(win->len_x-ELW_BOX_SIZE, 0, 0); glEnd(); glEnable(GL_TEXTURE_2D); draw_string(win->len_x-(ELW_BOX_SIZE-4), 2, (const unsigned char*) "X", 1); } return 1; } int draw_window(window_info *win) { int ret_val=0; if(win == NULL || win->window_id < 0) return -1; if(!win->displayed) return 0; // mouse over processing first elwin_mouse= mouseover_window(win->window_id, mouse_x, mouse_y); // now normal display processing glPushMatrix(); glTranslatef((float)win->cur_x, (float)win->cur_y, 0.0f); draw_window_title(win); draw_window_border(win); glColor3f(1.0f, 1.0f, 1.0f); if(win->display_handler) { ret_val=(*win->display_handler)(win); } else { ret_val=1; } glPopMatrix(); return(ret_val); } void show_window(int win_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return; if(windows_list.window[win_id].window_id != win_id) return; // pull to the top if not currently displayed if(!windows_list.window[win_id].displayed) select_window(win_id); windows_list.window[win_id].displayed= 1; } void hide_window(int win_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return; if(windows_list.window[win_id].window_id != win_id) return; windows_list.window[win_id].displayed= 0; } void toggle_window(int win_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return; if(windows_list.window[win_id].window_id != win_id) return; if(windows_list.window[win_id].displayed) windows_list.window[win_id].displayed= 0; else { // pull to the top if not currently displayed if(!windows_list.window[win_id].displayed) select_window(win_id); windows_list.window[win_id].displayed= 1; } } int get_show_window(int win_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return 0; if(windows_list.window[win_id].window_id != win_id) return 0; return windows_list.window[win_id].displayed; } int display_window(int win_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return -1; if(windows_list.window[win_id].window_id != win_id) return -1; // is it active? if(windows_list.window[win_id].displayed) { return(draw_window(&windows_list.window[win_id])); } return 0; } int mouse_in_window(int win_id, int x, int y) { // NOTE: these tests do not take depth into account, just location // Returns -1 on error, 0 No, 1 yes if(win_id <=0 || win_id >= windows_list.num_windows) return -1; if(windows_list.window[win_id].window_id != win_id) return -1; if(x =windows_list.window[win_id].cur_x+windows_list.window[win_id].len_x) return 0; if(y =windows_list.window[win_id].cur_y+windows_list.window[win_id].len_y) return 0; return 1; } int click_in_window(int win_id, int x, int y, Uint32 flags) { window_info *win; int _x, _y; if(mouse_in_window(win_id, x, y) > 0) { // watch for needing to convert the globals into the flags // TODO: put this in the window manager if(!flags){ if(shift_on) flags |= ELW_SHIFT; if(ctrl_on) flags |= ELW_CTRL; if(alt_on) flags |= ELW_ALT; if(right_click) flags |= ELW_RIGHT_MOUSE; //if(mid_click) flags |= ELW_MID_MOUSE; if(left_click) flags |= ELW_LEFT_MOUSE; //if(double_click) flags |= ELW_DBL_CLICK; } win= &windows_list.window[win_id]; _x= x - win->cur_x; _y= y - win->cur_y; //check the X for close - but hide it if(win->flags&ELW_CLOSE_BOX) { if(_y>0 && _y<=20 && _x>(win->len_x-20) && _x<=win->len_x) { // the X was hit, hide this window hide_window(win_id); return 1; } } //use the handler if(win->click_handler != NULL){ int ret_val; glPushMatrix(); glTranslatef((float)win->cur_x, (float)win->cur_y, 0.0f); ret_val= (*win->click_handler)(win, _x, _y, flags); glPopMatrix(); //return ret_val; // with click-thru return 1; // no click-thru permitted } else { return 1; } } return 0; } int mouseover_window(int win_id, int x, int y) { int _x, _y; int ret_val=0; if(mouse_in_window(win_id, x, y) > 0) { //use the handler if present if(windows_list.window[win_id].mouseover_handler){ _x= x - windows_list.window[win_id].cur_x; _y= y - windows_list.window[win_id].cur_y; glPushMatrix(); glTranslatef((float)windows_list.window[win_id].cur_x, (float)windows_list.window[win_id].cur_y, 0.0f); ret_val= (*windows_list.window[win_id].mouseover_handler)(&windows_list.window[win_id], _x, _y); glPopMatrix(); } #ifdef ELC if(!ret_val) { if(current_cursor!=CURSOR_ARROW)change_cursor(CURSOR_ARROW); } #endif //ELC return 1; } return 0; } void *set_window_handler(int win_id, int handler_id, int (*handler)() ) { void *old_handler; if(win_id <=0 || win_id >= windows_list.num_windows) return NULL; if(windows_list.window[win_id].window_id != win_id) return NULL; // save the information switch(handler_id){ case ELW_HANDLER_INIT: old_handler= (void *)windows_list.window[win_id].init_handler; windows_list.window[win_id].init_handler=handler; break; case ELW_HANDLER_DISPLAY: old_handler= (void *)windows_list.window[win_id].display_handler; windows_list.window[win_id].display_handler=handler; break; case ELW_HANDLER_CLICK: old_handler= (void *)windows_list.window[win_id].click_handler; windows_list.window[win_id].click_handler=handler; break; case ELW_HANDLER_MOUSEOVER: old_handler= (void *)windows_list.window[win_id].mouseover_handler; windows_list.window[win_id].mouseover_handler=handler; break; default: old_handler=NULL; } return old_handler; } int set_window_color(int win_id, Uint32 color_id, float r, float g, float b, float a) { if(win_id <=0 || win_id >= windows_list.num_windows) return 0; if(windows_list.window[win_id].window_id != win_id) return 0; // save the information switch(color_id){ case ELW_COLOR_BACK: windows_list.window[win_id].back_color[0]= r; windows_list.window[win_id].back_color[1]= g; windows_list.window[win_id].back_color[2]= b; windows_list.window[win_id].back_color[3]= a; return 1; case ELW_COLOR_BORDER: windows_list.window[win_id].border_color[0]= r; windows_list.window[win_id].border_color[1]= g; windows_list.window[win_id].border_color[2]= b; windows_list.window[win_id].border_color[3]= a; return 1; case ELW_COLOR_LINE: windows_list.window[win_id].line_color[0]= r; windows_list.window[win_id].line_color[1]= g; windows_list.window[win_id].line_color[2]= b; windows_list.window[win_id].line_color[3]= a; return 1; } return 0; } int use_window_color(int win_id, Uint32 color_id) { if(win_id <=0 || win_id >= windows_list.num_windows) return 0; if(windows_list.window[win_id].window_id != win_id) return 0; // save the information switch(color_id){ case ELW_COLOR_BACK: glColor4f(windows_list.window[win_id].back_color[0], windows_list.window[win_id].back_color[1], windows_list.window[win_id].back_color[2], windows_list.window[win_id].back_color[3]); return 1; case ELW_COLOR_BORDER: glColor3f(windows_list.window[win_id].border_color[0], windows_list.window[win_id].border_color[1], windows_list.window[win_id].border_color[2]); return 1; case ELW_COLOR_LINE: glColor3f(windows_list.window[win_id].line_color[0], windows_list.window[win_id].line_color[1], windows_list.window[win_id].line_color[2]); return 1; } return 0; }