JAL Computing

 


M-VC Open Motif Project

Here is a simple object based sample Open Motif program that places a button on a window. You pass a pointer to a callback function to the button. When the user presses the button, your callback function is called. In this case, the callback function prints out a message to the terminal window and then pops up a message box. To compile this code you will need to download the Open Motif package. You can do this with FINK. If you have trouble getting this to compile and link check here. If you connect to this program remotely using X11 forwarding, you do _not_ need to install the Open Motif library on the local computer, the X11 "server".

Note: The use of a callback function is somewhat similar in function to calling an abstract method in a base class. The concrete class defines the implementation details. In this program, the callback function defines the implementation details. Unfortunately, callbacks do not play well in C++. In this solution, we pass a pointer to this when we register the callback. The callback function is a static method that takes the pointer and cast it back to its proper type.

This project demonstrates the use of the M-VC architecture. The Model class contains the program algorithms and knows nothing about the presentation. The View-Controller class contains an instance of the Model class, displays the View and responds to user and system input. The Unix programmer may recognize this architecture as ENGINE-INTERFACE. Although this sample is written in C++, only the object based aspects of C++ appear valid when invoked directly from an Open Motif callback. In other words, Open Motif callbacks support C++ without inheritance, pure virtual classes (interfaces) or polymorphism.

// *** BEGIN PROJECT ***

/*
 *  viewcontroller.h
 *  M-VCMotif
 *
 *  Created by Jeff Louie on Thu Mar 04 2004.
 *  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
 *
 */
#ifndef VIEW_CONTROLLER_H
#define VIEW_CONTROLLER_H 1
#include <iostream.h>
#include <string.h>
#include <exception>
/* include the X library headers */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include "model.h"
#include "modalinfodialog.h"
// include OpenMotif headers
#include <Xm/Xm.h>  // --> <X11/Intrinsic.h>, <X11/StringDefs.h> 
#include <Xm/XmAll.h> // --> #include <Xm/PushB.h>
class ViewController {
	public:
		ViewController(int argc, char ** const argv);
		//virtual ~ViewController();
		static void doItPushButtonCallback(Widget w, 
			XtPointer client_data, 
               		XmPushButtonCallbackStruct * cbs);
		
	private:
		Widget shell, form1, pane1, rowColumn1, label1, button1;
		XtAppContext  app;
		Model model;  // creates an instance of the Model Class
		void doItPushButtonHandler();
};
			   
			   
#endif
//
//  viewcontroller.cpp
//  main.cpp 
//  M-VCMotif an object based Open Motif program
//  by Jeff Louie 02.26.2004
//
//  Demonstrates separating out the algorithms into a separate Model class.
//  Presentation and event handling code goes into the ViewController class.
//  Callback Solution as in Object Oriented Programming With C++ and Osf/Motif 
//  by Douglas A. Young 
//
#include <viewcontroller.h>
// application entry point
int main(int argc, char **argv) 
{    
	// create an instance of ViewController
	ViewController vc(argc,argv); // contains an instance of the Model
	return 0;
}
// ViewController Class
// Contains an instance of the Model Class 
// Using composition or containment by ownership
// Class Constructor
ViewController::ViewController(int argc, char ** argv) {
	// Initialize XT Intrinsics
    	shell = XtVaAppInitialize(&app, 
		"TestWidget", 
		NULL, 
		0,
        	&argc, 
		argv, 
		NULL, 
		NULL);
		
	// create a form
	form1= XtCreateManagedWidget("form1",
			xmFormWidgetClass,
			shell,
			NULL,
			0);
		
	// create a vertical pane
	pane1= XtCreateManagedWidget("pane1", 
			xmPanedWindowWidgetClass, 
			form1,NULL, 
			0);
	
	// create a row
	rowColumn1= XtCreateManagedWidget("rowColumn1",
			xmRowColumnWidgetClass,
			pane1,
			NULL,
			0);
	
	// create a Label
	label1= XtCreateManagedWidget("Press Me", 
			xmLabelWidgetClass, 
			rowColumn1  ,
			NULL,
			0);
	
	// create a labeled button
    	button1 = XtCreateManagedWidget("DoIt",
			xmPushButtonWidgetClass, 
			rowColumn1, 
			NULL, 
			0);
	   
    	// Register our callback with the widget
	// I hacked the code here, but it seems to work.
	// Callbacks don't play well in C++. 
	// In this solution we pass a pointer to this as an XtPointer
	// We use a static method doItPushButtonHandler to implement the callback
    	XtAddCallback(button1, XmNactivateCallback,
		(XtCallbackProc)&ViewController::doItPushButtonCallback,
		(XtPointer)this);
	
	// Associate widget with a window
	// Widget will be visible when it is managed, 
	// realized and mapped (window is displayed)
    	XtRealizeWidget(shell);
	// enter event loop
	// From the docs:
	/*The code for the input processing loop looks something like this: 
	while(TRUE) { 
		XEvent event; 
		XtAppNextEvent(app, &event); 
		XtDispatchEvent(&event);
	 } */
    	XtAppMainLoop(app);
}
void ViewController::doItPushButtonHandler()
{
	model.doIt();
	ModalInfoDialog(shell,"Information","Model");
}
// virtual destructor
//ViewController::~ViewController {;}
// Our callback function
// Sort of a high level event handler
// From the docs
/* Each callback procedure is a function of type XtCallbackProc. 
The procedure takes three arguments: a widget and two pointers to data.*/
// Again, callbacks don't play well in C++. In this solution we use a 
// static callback. We cast the (XtPointer) this back to a ViewController * 
// and call our instance event handler
void ViewController::doItPushButtonCallback(Widget w, 
		XtPointer client_data, 
		XmPushButtonCallbackStruct *cbs) {
	ViewController *p= (ViewController*)client_data;
	p->doItPushButtonHandler();
}
// You can do a Mac OS10.3 manual build from the command line. 
// g++ calls gcc and links to the c++ standard library
// note the lack of a call to -lX11!
// > g++ viewcontroller.cpp -o TestWidget 
//   -I./ -I/usr/x11r6/include/x11/ -L/usr/x11r6/lib -lXm -lXt
// Using XCode enter the header path and linker commands
// from the Project Info window.
// You can create a text file named TestWidget and set the app
// properties for TestWidget
// >cd /etc/X11/app-defaults
// >sudo exemacs TestWidget
// xemacs--> 
// 	*geometry:200X30 
// 	*rowColumn1*orientation:horizontal
// 	*rowColumn1*numColumns: 2
// Or you can pass the geometry on the command line 
// >TestWidget -geometry 200X30
/*
 *  model.h
 *  M-VCMotif
 *
 *  Created by Jeff Louie on Thu Mar 04 2004.
 *  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
 *
 */
#ifndef MODEL_H
#define MODEL_H 1
#include <iostream.h>
#include <string.h>
#include <exception>
class Model {
	public:
		Model();
		//Model(Model &model);
		//virtual ~Model();
		void doIt();
};
#endif
/*
 *  model.cpp
 *  M-VCMotif
 *
 *  Created by Jeff Louie on Thu Mar 04 2004.
 *  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
 *
 */
#include "model.h"
// Model Class
// Class Constructor
Model::Model(){;}
// virtual destructor
// virtual Model::~Model(){;}
// copy constructor
// Model::Model(Model &model) {}
// YOUR COMPLEX ALGORITHM GOES HERE
void Model::doIt() {
	cout << "Do It" << endl;
}
/*
 *  modalinfodialog.h
 *  M-VCMotif
 *
 *  Created by Jeff Louie on Thu Mar 04 2004.
 *  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
 *
 *  Pops up a modal information dialog
 */
#ifndef MODAL_INFO_DIALOG_H
#define MODAL_INFO_DIALOG_H 1
#include <Xm/Xm.h>
#include <Xm/MessageB.h>
#include <string>
//#include <iostream.h>
class ModalInfoDialog {
	public:
		ModalInfoDialog(Widget parent, 
			std::string title, 
			std::string message);
		//virtual ~ModalPop();
};
#endif
/*
 *  modalinfodialog.cpp
 *  M-VCMotif
 *
 *  Created by Jeff Louie on Thu Mar 04 2004.
 *  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
 *
 */
#include "modalinfodialog.h"
ModalInfoDialog::ModalInfoDialog(Widget parent, 
		std::string title, 
		std::string message) {
	Widget dialog;
	
	char strTitle[strlen(title.c_str())+1];
	strcpy(strTitle,title.c_str());
	dialog= XmCreateInformationDialog(parent, strTitle ,NULL, 0);
	const char * strMessage= message.c_str(); // valid through next line only
	XtVaSetValues(dialog,
		XmNdialogStyle,
		XmDIALOG_FULL_APPLICATION_MODAL,
		XtVaTypedArg, 
		XmNmessageString,
		XmRString, 
		strMessage, 
		strlen (strMessage) +1,
		NULL);
	XtManageChild(dialog);
	while(XtIsManaged(dialog)) 
	{
		XEvent event;
		XtAppNextEvent(XtWidgetToApplicationContext(dialog), &event);
		XtDispatchEvent(&event);
	}
	XtDestroyWidget(dialog);
}
// *** END PROJECT ***
Have fun!
Send mail to [email protected] with questions or comments about this web site. Copyright © 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 © 
Last modified: 08/04/09
Hosted by www.Geocities.ws

1