My GUI... check, optimization, hints...

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:My GUI... check, optimization, hints...

Post by Pype.Clicker »

imho, an updated GUI.EXE is of little use ... what can we do with it ? just see it goes ?fast? (with 60 windows at max, there are chances we won't even notice the difference between the 2 versions if your redrawing function are in the same process than the event processing ...)

oh, or maybe we could dissassemble the GUI.EXE to get the assembler out of it and see it's not even optimized ? no thanks: you can keep your EXE on your HDD: i prefer crawling back in my backup CD and find back the crappy code i wrote 5 years ago :p
Tim

Re:My GUI... check, optimization, hints...

Post by Tim »

You don't really need a specific sort function if all you're doing it moving windows relative to each other.

e.g.:
Bring window to front -> insert at end of list
Move window to bottom -> insert at beginning of list
Keep window on top -> keep at end of list
Clip window to siblings -> remove areas from clip list for all windows after this window in the list

You don't need a separate VB-style 'zorder' property. Additionally, I think that Windows' tab order is the same as its z-order: you don't often overlap controls on dialogs, and you don't often tab between top-level windows, so it makes sense to skip to the next window in the z-order when you press Tab.
warmaster199atschool

Re:My GUI... check, optimization, hints...

Post by warmaster199atschool »

Right, I'll just ignore P.C for now... Fine, no GUI.EXE for you :p - so go get your old code.

Back to business:
As for linked lists and such, I have had no experience with these. I have tried another one of my wierd ideas - I created a sort function that supposedly does this: Get all the window's zorders in order and put them in order (0-63) into a temporary window array (I bet that sounds odd). After the sorting is complete, it transfers the temporary window array into wm_elements, over writing them all... I call that function right at the end of movefrontwin and everything seems fine. I change the drawgui function by deleting the extra loop and making appropriate changes. Right after I do that, the GUI doesn't draw correctly. Does anyone have a sort idea that would do minimum damage to my code?
Tim

Re:My GUI... check, optimization, hints...

Post by Tim »

I'll say this again: you don't need to keep track of the z-order for each window.

Don't use arrays at all. Keep a linked list of child windows for every window (top-level windows go into the root window's list), and keep that list sorted all the time -- when you add a window into that list, put it in the correct place. When you create a window, you probably want it to become the active window, right? So when you create a window, you just add it to the end of its parent's list. No arrays. No sort functions. Just a linked list.

BTW, if you really do have no experience with linked lists, I suggest you read up on them very soon, because you will use them all over your OS. Also useful are trees and hash tables.
warmaster199atschool

Re:My GUI... check, optimization, hints...

Post by warmaster199atschool »

OK, here's the source for my GUI(not full source - doesn't fit - had to cut out half of it). It's the only way that you people could really see what's happening. I reverted back to my previous code without the sort function. The sort function is still there, but it is never called. Get ready for a long list.

Code: Select all

#define MAXWINDOWS 64

struct WINDOW
{
    unsigned short x;
    unsigned short y;
    unsigned short width;
    unsigned short height;
    unsigned char *caption;
    unsigned short zorder;
    unsigned long flags;
    unsigned char handle;
};

struct WINDOW wm_elements [MAXWINDOWS];

void initwm()
{
    int i;

    for (i = 0; i < MAXWINDOWS; i++)
    {
        wm_elements[i].handle = i;
        wm_elements[i].flags = 0;
    }
}   

void drawgui()
{
    int tz;
    int i;

    for (tz = MAXWINDOWS - 1; tz >= 0; tz--)
    {                   
        for (i = 0; i < MAXWINDOWS; i++)
        {   
            if (wm_elements[i].flags & WMFLAGS_ACTIVE)
            {
                if (wm_elements[i].zorder == tz)
                {
                    if (wm_elements[i].flags & WMFLAGS_BORDER)
                        windowbox(wm_elements[i].x, wm_elements[i].y, (wm_elements[i].x + wm_elements[i].width), (wm_elements[i].y + wm_elements[i].height));
                    else
                        drawrect(wm_elements[i].x, wm_elements[i].y, (wm_elements[i].x + wm_elements[i].width), (wm_elements[i].y + wm_elements[i].height), 24);
                }
            }
        }
    }
}

void winzsort()
{
    struct WINDOW tempstruct[MAXWINDOWS];
    int tz, i;

    for(i = 0; i < MAXWINDOWS - 1; i++)
    {
        if (wm_elements[i].flags & WMFLAGS_ACTIVE)
        {
            for (tz = 0; tz < MAXWINDOWS - 1; tz++)
            {
                if (wm_elements[i].zorder == tz)
                {
                    tempstruct[tz] = wm_elements[i];
                }
            }
        }
    }

    for (i = 0; i < MAXWINDOWS - 1; i++)
    {
        wm_elements[i] = tempstruct[i];
    }                                  
}

void movefrontwin(unsigned char handle)
{
    int tz, i;
    unsigned char t_zorder = wm_elements[handle].zorder;

    for (i = 0; i < MAXWINDOWS; i++)
    {
        if (t_zorder > wm_elements[i].zorder)
        {
            wm_elements[i].zorder++;
        }
    }
    wm_elements[handle].zorder = 0;
}

unsigned char inwhatwin(int x, int y)
{
    unsigned int tz;
    unsigned char i;

    for (tz = 0; tz < MAXWINDOWS; tz++)
    {
        for (i = 0; i < MAXWINDOWS; i++)
        {
            if (wm_elements[i].flags & WMFLAGS_ACTIVE)
            {
                if (wm_elements[i].zorder == tz)
                {         
                    if ((x >= wm_elements[i].x) && (x < (wm_elements[i].x + wm_elements[i].width)))
                        if ((y >= wm_elements[i].y) && (y < (wm_elements[i].y + wm_elements[i].height)))
                            return i;
                }
            }
        }
    }

    return 255;
}

I am sorry I could not log on to actually post this file, My school disabled cookies in a sad attempt to disable hotmail access - now hotmail doesn't use cookies... Totally useless school board we have here... :-\
Tim

Re:My GUI... check, optimization, hints...

Post by Tim »

Maybe you don't understand my previous two posts. I'll rewrite some of your code then.

Code: Select all

#define MAXWINDOWS 64
Remove this. Don't impose a limit.

Code: Select all

struct WINDOW
{
    unsigned short x;
    unsigned short y;
    unsigned short width;
    unsigned short height;
    unsigned char *caption;
    unsigned short zorder;
Don't need this if your window lists are always sorted.

Code: Select all

    unsigned long flags;
    unsigned char handle;
};
Add:

Code: Select all

struct WINDOW *prev, *next;
    struct WINDOW *first_child, *last_child;
    struct WINDOW *parent;
prev and next are the pointers to the previous and next children within the parent's list of children. first_child and last_child define this window's list of children (possibly empty). parent provides a link up to the window's parent.

Code: Select all

struct WINDOW wm_elements [MAXWINDOWS];
Use malloc to allocate your windows. This will give you a virtually unlimited number of windows without wasting any space for unused elements. If you want to use window handles, have a dynamically-allocated handle-to-window array:

Code: Select all

struct WINDOW** wm_handles;
unsigned num_windows;

typedef unsigned WINDOW_HANDLE;
WINDOW_HANDLE allocate_window(void)
{
    struct WINDOW *wnd;
    wnd = malloc(sizeof(*wnd));
    wm_handles = realloc(wm_handles, sizeof(WINDOW*) * (num_windows + 1));
    wm_handles[num_windows] = wnd;
    memset(wnd, 0, sizeof(*wnd));
    wnd->handle = num_windows++;
    return wnd->handle;
}

Code: Select all

void initwm()
{
    int i;

    for (i = 0; i < MAXWINDOWS; i++)
    {
        wm_elements[i].handle = i;
        wm_elements[i].flags = 0;
    }
}
Don't need any of this.

Code: Select all

void drawgui()
{
<snip>
}
You should virtually never need to redraw the entire screen. Instead, record an "invalid rectangle" for each window: that is, an area within each window which should be repainted next time the application is ready.

Code: Select all

void winzsort()
{
<snip>
}
Not necessary since the z-order is defined by the ordering of each window's list of children.

Code: Select all

void movefrontwin(unsigned char handle)
{
    int tz, i;
    unsigned char t_zorder = wm_elements[handle].zorder;

    for (i = 0; i < MAXWINDOWS; i++)
    {
        if (t_zorder > wm_elements[i].zorder)
        {
            wm_elements[i].zorder++;
        }
    }
    wm_elements[handle].zorder = 0;
}
Better:

Code: Select all

void movefrontwin(WINDOW_HANDLE handle)
(using unsigned char limits you to 256 windows total)

Code: Select all

{
    struct WINDOW *wnd;
    if (handle >= num_windows)
        return;
    wnd = wm_handles[handle];
    if (wnd == NULL)
        return;

    /* Remove window from the parent's list of children */
    if (wnd->prev != NULL)
        wnd->prev->next = wnd->next;
    if (wnd->next != NULL)
        wnd->next->prev = wnd->prev;
    if (wnd == wnd->parent->first_child)
        wnd->parent->first_child = wnd->next;
    if (wnd == wnd->parent->last_child)
        wnd->parent->last_child = wnd->prev;

    /* Add window to end of parent's list of children */
    wnd->prev = wnd->parent->last_child;
    wnd->next = NULL;
    if (wnd->parent->last_child != NULL)
        wnd->parent->last_child->next = wnd;
    wnd->parent->last_child = wnd;
    if (wnd->parent->first_child == NULL)
        wnd->parent->first_child = wnd;
}

Code: Select all

unsigned char inwhatwin(int x, int y)
{
<snip>
}
See my alternate code for this function earlier in the thread.
Warmaster199

Re:My GUI... check, optimization, hints...

Post by Warmaster199 »

[attachment deleted by admin]
Tim

Re:My GUI... check, optimization, hints...

Post by Tim »

[attachment deleted by admin]
warmaster199atschool

Re:My GUI... check, optimization, hints...

Post by warmaster199atschool »

I must say thanks alot for the modifications. It is somewhat better cleared up now - partially because of the fact that I read both the linked list and binary tree tutorials at http://www.cprogramming.com (they seem good to me).

I took a quick scan of your code and it looks good to me. By the looks of the structure of this system, it looks like it supports windows inside of windows (MDI - Multiple Document Interfaces). If not, It seems so easy to add on top of this new code. I will definitely add you to my O.S.'es credits (Under special thanks). I have decided that I will recreate my GUI(Decided this last night after reading the tutorials). I wrote up a basic tree on paper as an example for my WM structure. It was based on your design and it makes total sence.

Once again, many thanks
Tim

Re:My GUI... check, optimization, hints...

Post by Tim »

Glad to be of help. :) I'll release my own GUI sources soon, which look fairly similar to this.

The child window stuff isn't so much to support MDI (although it could), but controls -- if you think of every text box, button and label as being a window in its own right, you can handle them all the same way (and just handle painting and user input differently).
Warmaster199

Re:My GUI... check, optimization, hints...

Post by Warmaster199 »

Do you have MSN? I may need help when I am writing my new gui. I'll have to read the tutorials again. The person at VBWorld made a reply as well. His idea was basically the same as yours but it didn't include the *parent struct and kept the window structs as is. He made a separate structure that is for the linked list. It was something like:

struct list
{
list* prev;
list* next;
WINDOW *data;
}

The main problem was he didn't have PowerC and therefore couldn't test it(Used VC++ to syntax check). When I checked it out the only error was that drawgui(); didn't work at all...
Post Reply