Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Designing a Cross-Platform GUI


April 1995/Designing a Cross-Platform GUI/Listing 2

Listing 2 gui.c — Implementation of platform-independent functions

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "gui.h"

extern int              charHeight;
extern FILE*            fErrLog;
extern GUI_APPLICATION* pGuiApplication;

//*** logging function into a file opened by GUI_APPLICATION

void Log(char* fmt, ...)
{
   va_list ap;

   if(fErrLog) {
     va_start(ap, fmt);
     vfprintf(fErrLog, fmt, ap);
     fflush(fErrLog);  // to protect against losing log if crashing
     va_end(ap);
   }
}

//*** Functions for GUI_APPLICATION

int GUI_APPLICATION::AddWindow(GUI_WINDOW *pWindow)
{
   int              ret = 1;
   GUI_WINDOW_ELEM* pTmp;

   // add a GUI_WINDOW to the linked list of windows
   if(pFree) {
     pTmp = pFree;
     pFree = pFree->pNext;
     pTmp->pWindow = pWindow;
     pTmp->pNext = pUsed;
     pUsed = pTmp;
     ret = 0;
   }

   if(ret) Log("Error: too many windows.\n");

   return(ret);
}

int GUI_APPLICATION::DelWindow(GUI_WINDOW* pWindow)
{
   int             ret = 1;
   GUI_WINDOW_ELEM *pTmp, *pPrev;

   // delete a window from the linked lists of windows
   for(pTmp = pUsed, pPrev = NULL; pTmp; pPrev = pTmp,
      pTmp = pTmp->pNext) {
     if(pTmp->pWindow == pWindow) {
       // take out of used list
       if(pPrev) pPrev->pNext = pTmp->pNext;
       else      pUsed        = pTmp->pNext;
       // put into free list
       pTmp->pNext = pFree;
       pFree = pTmp;
       ret = 0;
       break;
     }
   }

   if(ret) Log("Error: can't delete window %p\n", pWindow);

   return(ret);
}

GUI_WINDOW* GUI_APPLICATION::FindWindow(NativeWindow window)
{
   GUI_WINDOW_ELEM *pTmp;

   // find a window in its list of windows
   for(pTmp = pUsed; pTmp; pTmp = pTmp->pNext) {
      if(pTmp->pWindow->GetNativeWindow() == window) break;
   }

   return(pTmp ? pTmp->pWindow : NULL);
}

//*** Functions for GUI_OBJECT

GUI_OBJECT::GUI_OBJECT(GUI_WINDOW* pParent, int id, int x, int y,
                   int width, int height)
          : id(id), pParent(pParent), x(x), y(y),
            width(width), height(height)
{
   // add this object to its parent children list
   if(pParent) pParent->AddChild(this);
}

GUI_OBJECT::~GUI_OBJECT(void)
{
   // delete this object from its parent children list
   if(pParent) pParent->DeleteChild(this);
}

//*** Functions for GUI_GRAPHICS_OBJECT

GUI_GRAPHICS_OBJECT::GUI_GRAPHICS_OBJECT(GUI_WINDOW* pParent, int id,
                                  int x, int y,
                                  int width, int height,
                                  int color, int lineWidth)
                 :GUI_OBJECT(pParent, id, x, y, width, height),
                  color(color), lineWidth(lineWidth)
{
   // nothing to do
}

GUI_GRAPHICS_OBJECT::~GUI_GRAPHICS_OBJECT(void)
{
   // nothing to do
}

//*** Functions for GUI_LINE

GUI_LINE::GUI_LINE(GUI_WINDOW* pParent, int id, int x1, int y1, int x2,
                int y2, int color, int lineWidth)
        :GUI_GRAPHICS_OBJECT(pParent, id, x1, y1, x2, y2, color, lineWidth)
{
   // paint the first time around
   Paint(pParent->GetGraphicsHandle());
}

//*** Functions for GUI_ELLIPSE

GUI_ELLIPSE::GUI_ELLIPSE(GUI_WINDOW* pParent, int id, int x, int y,
                int width, int height,
                int color, int fillType, int lineWidth)
          :GUI_GRAPHICS_OBJECT(pParent, id, x, y, width, height,
                           color, lineWidth),
           fillType(fillType)
{
   // paint the first time around
   Paint(pParent->GetGraphicsHandle());
}

//*** Functions for GUI_WINDOW_OBJECT

GUI_WINDOW_OBJECT::GUI_WINDOW_OBJECT(GUI_WINDOW* pParent, int id,
                                     int x, int y, int width, int height)
                                     :GUI_OBJECT(pParent, id, x, y, width, height)
{
   window = 0;
}

//*** Functions for GUI_WINDOW

int GUI_WINDOW::AddChild(GUI_OBJECT* pChild)
{
   int              ret = 1;
   GUI_OBJECT_ELEM* pTmp;

   // add pChild to the linked list of children
   if(pFree) {
     pTmp = pFree;
     pFree = pFree->pNext;
     pTmp->pObject = pChild;
     pTmp->pNext = pUsed;
     pUsed = pTmp;
     ret = 0;
}

   if(ret) Log("Error: too many children.\n");

   return(ret);
}

int GUI_WINDOW::DeleteChild(GUI_OBJECT* pChild)
{
   int             ret = 1;
   GUI_OBJECT_ELEM *pTmp, *pPrev;

   // delete pChild from the linked list of children
   for(pTmp = pUsed, pPrev = NULL; pTmp; pPrev = pTmp,
      pTmp = pTmp->pNext) {
     if(pTmp->pObject == pChild) {
        // take out of used list
        if(pPrev) pPrev->pNext = pTmp->pNext;
        else      pUsed        = pTmp->pNext;
        // put into free list
        pTmp->pNext = pFree;
        pFree = pTmp;
        ret = 0;
        break;
     }
   }

   if(ret) Log("Error: can't delete child %p\n", pChild);

   return(ret);
// get child pointer from its id; it returns NULL if fails

GUI_OBJECT* GUI_WINDOW::GetChildFromId(int id)
{
   GUI_OBJECT_ELEM *pTmp;

   for(pTmp = pUsed; pTmp; pTmp = pTmp->pNext) {
     if(pTmp->pObject->GetId() == id) break;
   }

   return(pTmp ? pTmp->pObject : NULL);
}

// get child pointer from its native window; it returns NULL if fails

GUI_OBJECT* GUI_WINDOW::GetChildFromWindow(NativeWindow hwnd)
{
   GUI_OBJECT_ELEM *pTmp;

   for(pTmp = pUsed; pTmp; pTmp = pTmp->pNext) {
      if(pTmp->pObject->GetNativeWindow() == hwnd) break;
   }

   return(pTmp ? pTmp->pObject : NULL);
}

/* End of File */

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.