Nekochan Net

Official Chat Channel: #nekochan // irc.nekochan.net
It is currently Tue Sep 02, 2014 9:21 am

All times are UTC - 8 hours


Forum rules


Any posts concerning pirated software or offering to buy/sell/trade commercial software are subject to removal.



Post new topic Reply to topic  [ 8 posts ] 
Author Message
Unread postPosted: Mon Apr 23, 2012 7:49 am 
Offline
User avatar

Joined: Tue Oct 12, 2004 2:54 pm
Posts: 289
Location: London, Ingerlund
Hi All,

I messed around with geo's code from here: http://forums.nekochan.net/viewtopic.php?f=15&t=16726405 to see if i could maybe find what was causing the odd 'jump to the left' artefact he was seeing on IRIX. Unfortunately, I think it's a bug in IRIX Motif for which obviously we'll never see a fix.

My little experiment left me with some code for a basic ViewKit component. So instead of deleting it, I thought I'd post it here. Perhaps somebody might find it interesting or useful.

Counter.C
Code:
/*
 Counter.C    A basic ViewKit component.

              (c)2012 under GPL, Avi Bercovich <avi@sillypages.org>
*/

#include <stdio.h>

#include <string>
#include <iostream>
using namespace std;

#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Frame.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>

#include <Vk/VkApp.h>
#include <Vk/VkSimpleWindow.h>

// the interval by which the counter increases or decreases
#define COUNTER_STEP 5

class Counter : public VkComponent {

   public:
   
      Counter(const char *name, Widget parent);
      ~Counter() {};

      virtual const char *className() { return "Counter"; }

      void    setCount(int count) { _count = count; }
      int    getCount() { return _count; }

      void    updateCounter();

   private:

      int _count;

      Widget ui_frame_counter;

      static String ui_defaultResources[];

      static void increase_cb(Widget w, XtPointer clientData, XtPointer callData);
      static void decrease_cb(Widget w, XtPointer clientData, XtPointer callData);
};


class CounterWindow : public VkSimpleWindow {

   public:

      CounterWindow(const char *name);
      ~CounterWindow() {};

      virtual const char *className() { return "CounterWindow"; }
};


String Counter::ui_defaultResources[] = {

   "*renderTable: normal14, bold24",
   "*fontType: FONT_IS_FONT",
   "*normal14.fontName: -*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*",
   "*bold24.fontName: -*-helvetica-bold-r-normal-*-24-*-*-*-*-*-*-*",

   NULL
};

Counter::Counter(const char *name, Widget parent) : VkComponent(name) {

   XmString _string;

   // _baseWidget remains unmanaged. The VkComponent->show() method called in main() takes care of that.
   _baseWidget = XtVaCreateWidget("BaseWidget", xmRowColumnWidgetClass, parent,

      XmNtopOffset, 5,
      XmNrightOffset,   5,
      XmNbottomOffset, 5,
      XmNleftOffset, 5,

      XmNnumColumns,          3,
      XmNorientation,         XmHORIZONTAL,
   
      NULL);

   // make sure ViewKit takes care of the widget destruction of our new VkComponent
   installDestroyHandler();
   
   // load font definitions, only works with Motif 2.1
   setDefaultResources(_baseWidget, ui_defaultResources);

   // create the Counter widgets and add the Xt callbacks for our buttons
   _string = XmStringCreate("-", "bold24");

   Widget ui_decrease_btn = XtVaCreateManagedWidget("DecreaseButton", xmPushButtonWidgetClass, _baseWidget,

      XmNlabelString, _string,

      NULL);   

   XtAddCallback(ui_decrease_btn, XmNactivateCallback, &Counter::decrease_cb, (XtPointer) this );

   Widget ui_frame = XtVaCreateManagedWidget("Frame", xmFrameWidgetClass, _baseWidget,

      XmNshadowType,    XmSHADOW_ETCHED_OUT,

      XmNrightOffset,   5,
      XmNleftOffset,    5,

      NULL);

   _string = XmStringCreate("Counter", "normal14");

   Widget ui_frame_label = XtVaCreateManagedWidget("FrameLabel", xmLabelWidgetClass, ui_frame,

      XmNframeChildType,             XmFRAME_TITLE_CHILD,
      XmNchildHorizontalAlignment,    XmALIGNMENT_END,

      XmNlabelString,    _string,

      NULL);

   _string = XmStringCreate("0", "bold24");

   ui_frame_counter = XtVaCreateManagedWidget("FrameCounter", xmLabelWidgetClass, ui_frame,

      XmNlabelString,         _string,

      NULL);

   _string = XmStringCreate("+", "bold24");

   Widget ui_increase_btn = XtVaCreateManagedWidget("IncreaseButton", xmPushButtonWidgetClass, _baseWidget,

      XmNlabelString, _string,

      NULL);   

   XtAddCallback(ui_increase_btn, XmNactivateCallback, &Counter::increase_cb, (XtPointer) this );

    // housekeeping...
   XmStringFree(_string);   

   // reset internal counter
   setCount(0);
}


void Counter::increase_cb(Widget w, XtPointer clientData, XtPointer callData) {

   // This is C++ casting magicke to get the actual object instance that triggered the callback
   Counter *obj = (Counter *) clientData;

   // Now that we have the correct object, we can deal with this event
   obj->setCount(obj->getCount() + COUNTER_STEP);
   obj->updateCounter();
}


void Counter::decrease_cb(Widget w, XtPointer clientData, XtPointer callData) {

   // This is C++ casting magicke to get the actual object instance that triggered the callback
   Counter *obj = (Counter *) clientData;

   // Now that we have the correct object, we can deal with this event   
   obj->setCount(obj->getCount() - COUNTER_STEP);
   obj->updateCounter();
}


void Counter::updateCounter() {

   // There's no way to feed XmStringCreate the 'count' parameter as an integer, So we need this nasty little C typing workaround.
   char bla[10];
   sprintf(bla, "%d", getCount());

   XmString _string = XmStringCreate(bla, "bold24");

   XtVaSetValues(ui_frame_counter,

      XmNlabelString, _string,

      NULL);

   XmStringFree(_string);
}


CounterWindow::CounterWindow(const char *name) : VkSimpleWindow(name) {

   Widget ui_root = XtCreateWidget("UIRoot", xmFormWidgetClass, mainWindowWidget(), NULL, 0);

   Counter *ui_counter = new Counter("Counter", ui_root);
   ui_counter->setCount(0);
   ui_counter->show();
   
   addView(ui_root);
}


int main(int argc , char *argv[]) {

   VkApp *app = new VkApp("Counter", &argc, argv);
   
   CounterWindow *win = new CounterWindow("Counter Window");
   win->show();

   app->run();
}


Makefile
Code:
APP_NAME = counter

APP_OBJS = Counter.o

INCDIRS = -I. -I/usr/local/include  -I/usr/nekoware/include
LIBDIRS   = -L/usr/local/lib -L/usr/nekoware/lib

STDLIBS      = -lm
STDCPPLIBS   = -lC -lCio
X11LIBS    = -lXt -lX11 -lPW
MOTIFLIBS   = -lSgm -lXm
VKLIBS       = -lvk

LIBS=      $(VKLIBS) \
      $(MOTIFLIBS)\
      $(X11LIBS)\
      $(STDCPPLIBS)\
      $(STDLIBS)

CXX      = CC
CXXOPTS    = -O2 -LANG:std

CC      = c99
COPTS      = -O2

all : $(APP_NAME)

$(APP_NAME): ${APP_OBJS}
   ${CXX} ${APP_OBJS} ${LIBDIRS} ${LIBS} -o ${APP_NAME}

%.o : %.c   
   ${CC} ${COPTS} ${INCDIRS} -c $<

%.o : %.C   
   ${CXX} ${CXXOPTS} ${INCDIRS} -c $<


clean :
   rm -rf ${APP_NAME} *.o core *~ ii_*

_________________
:Fuel: redbox 800Mhz 4Gb V12


Top
 Profile  
 
Unread postPosted: Thu May 03, 2012 7:08 am 
Offline
User avatar

Joined: Tue Jul 21, 2009 4:07 am
Posts: 523
Location: Shenzhen, P.R.C
hi jimmer thanks for sharing this code :)

btw, got a quick question, is it possible to pass more than one widget as client data on a callback? Example is my case, i have a button callback. Inside the callback i need to check two widgets to accomplish a task.

My original way was to declare the two widget as global, but this way is not applicable for me because it would left me a design limitation or flaw. So that's why i should pass the widget properly through the callback right? but i need to pas two of them so how can i pass the two widget? i already tried many way but everyone will cause segmantation fault :(

i already tried, pass by value, pass by reference, pass by pointer of widget array, structure which contains the address of the widget.. still the same :( hoping you could enlighten me with some code snippets :) thanks in advance, night!

_________________
:Octane: (Sakura) :O2: (Sasuke) :1600SW: (Naruto) ... lil Jesse! (O2 laptop)
“Imagination is more important than knowledge.“ – A. Einstein


Top
 Profile  
 
Unread postPosted: Thu May 03, 2012 11:00 am 
Offline
User avatar

Joined: Tue Oct 12, 2004 2:54 pm
Posts: 289
Location: London, Ingerlund
I wouldn;t have thought there would be any issues with passing a struct containing more than one widget, but you seem to have discovered there is. Who knew. That said, my solution would be to not access the other widgets at all, but have them modify some datastructure - and then I;d read the datastructure rather than the widget. oh wait... that's what the MVC pattern is all about!

My advice/approach would be to refactor your code so that the app state is contained in a Model and then implement a bunch of callbacks to push Model changes to the UI.

But I would say something like that as I;ve been messing with Android for the last few months.

grts,

J

_________________
:Fuel: redbox 800Mhz 4Gb V12


Top
 Profile  
 
Unread postPosted: Thu May 03, 2012 4:44 pm 
Offline
User avatar

Joined: Tue Jul 21, 2009 4:07 am
Posts: 523
Location: Shenzhen, P.R.C
morning jummer!

jimmer wrote:
I wouldn;t have thought there would be any issues with passing a struct containing more than one widget, but you seem to have discovered there is. Who knew.

hehe maybe i implemented it wrong? but really i tried it but no success, also i think i did it right coz got used on pass by pointer coz on embedded field :) but i hope someone can also confirm if this is indeed another issue with motif

jimmer wrote:
That said, my solution would be to not access the other widgets at all, but have them modify some datastructure - and then I;d read the datastructure rather than the widget. oh wait... that's what the MVC pattern is all about!

My advice/approach would be to refactor your code so that the app state is contained in a Model and then implement a bunch of callbacks to push Model changes to the UI.

geeez you really are a guru! hehe thanks for the advice!! why i never thought about that way hehe so meaning instead of sending the widgets, ill make a structure that will hold the two datas that i need. so the two datas will be filled by another two callbacks which is from the two widget... ok will try your approach and report back later, thanks jimmer!!!

jimmer wrote:
But I would say something like that as I;ve been messing with Android for the last few months.

aha!! so you messing with java now right? been there last year, but i stopped coz got busy with work :) also got frustrated with the development kit hehe

_________________
:Octane: (Sakura) :O2: (Sasuke) :1600SW: (Naruto) ... lil Jesse! (O2 laptop)
“Imagination is more important than knowledge.“ – A. Einstein


Top
 Profile  
 
Unread postPosted: Fri May 04, 2012 7:06 am 
Offline
User avatar

Joined: Tue Jul 21, 2009 4:07 am
Posts: 523
Location: Shenzhen, P.R.C
hi jimmer, tried your advice, still nothing :( i even tried to pass the simplest structure, the callback cannot receive the expected data, really strange, is this a bug? or design limitation?

_________________
:Octane: (Sakura) :O2: (Sasuke) :1600SW: (Naruto) ... lil Jesse! (O2 laptop)
“Imagination is more important than knowledge.“ – A. Einstein


Top
 Profile  
 
Unread postPosted: Fri May 04, 2012 8:30 am 
Offline
User avatar

Joined: Tue Oct 12, 2004 2:54 pm
Posts: 289
Location: London, Ingerlund
Not sure why you're still trying to pass the structure to your widget. You should try and setup a globally accessible datastructure to keep track of the UI and its state. Then read from that datastructure what you need, when you need.

Say your 2 other widgets are text boxes, if the text in any of those widget changes you put the new values into the global datastructure. When you fire the callback of the third widget in which you need to use the textbox values, you don't query the textboxes themselves, rather you ask the global datastructure for the stored values. This way keeping track of component access and pointers etc. simply goes away, which is the whole point of the Model-View-Controller (MVC) pattern.

Of course there are exceptions etc. but on the whole it works pretty well.

J.


Top
 Profile  
 
Unread postPosted: Sat May 05, 2012 12:16 am 
Offline
User avatar

Joined: Tue Jul 21, 2009 4:07 am
Posts: 523
Location: Shenzhen, P.R.C
EUREKA!!! i found it jimmer!! hehe now everything worked as planned hehe before i explain my solution ill answer your post first :) actually i already tried your advice and yes it worked but as i mentioned earlier, i cannot use global because it will contradict with the design of application. to elaborate more, i have a function that will create a custom made popup dialog. one of the buttons callback needs two information, one from a list widget, the other from a text widget. note that using the function, i can instantiate many pop-up dialogs and each instance can have different values for each widget. so if i will use global, if i press button from 1st dialog, its possible to get the values set by the 2nd dialog. so to handle this case, i only need local variable from the function so that every time the function is called, a new instance is created in which the widgets are done. hehe i hope i explained my case here, anyway now for the solution:

just to share maybe anyone will stumble to this same issue, looking at many reference about Motif, i didn't encounter passing more than one widget to a callback hehe na ja, here is what i learned:

to pass two widgets, use
Code:
Widget* SENDDIALOG_ClientData = malloc((sizeof(Widget)*2));


then create the widgets by
Code:
...
...
SENDDIALOG_ClientData[0] = XmCreateScrolledList (SENDDIALOG_Form_Upper, "Users", args, n);
XtManageChild (SENDDIALOG_ClientData[0]);
...
...
SENDDIALOG_ClientData[1] = XmCreateScrolledText(SENDDIALOG_Form_Lower, "Message", args, n);
XtManageChild (SENDDIALOG_ClientData[1]);
...
...


then register callback by
Code:
XtAddCallback (SENDDIALOG_BtnG_Send, XmNactivateCallback, sendDialog_SendCallBack, (XtPointer)SENDDIALOG_ClientData);


then in callback, unwrap data by
Code:
Widget* SENDDIALOG_List_Users = (Widget*)client_data;
Widget* SENDDIALOG_Text_Message = (Widget*)client_data+1;


hehe i think this is known already by everyone here but hehe want to share my happiness by this :)
thanks jimmer for your replies, hopefully can show my work here soon!

_________________
:Octane: (Sakura) :O2: (Sasuke) :1600SW: (Naruto) ... lil Jesse! (O2 laptop)
“Imagination is more important than knowledge.“ – A. Einstein


Top
 Profile  
 
Unread postPosted: Sat May 05, 2012 7:08 pm 
Offline
User avatar

Joined: Tue Oct 12, 2004 2:54 pm
Posts: 289
Location: London, Ingerlund
Good to hear you've solved your issue. Looking forward to seeing your software :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group