/******************************************************************************
*
* Copyright (c) 2014-2016 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* View.h
*
*****************************************************************************/
// 2015/01/18 Updated to add grabPointer, ungrabPointer methods.
// 2015/01/26 Added set method which takes a pointer to RenderTable class.
// 2015/02/11 Added mulitiple queryMousePointer methods.
// 2015/02/20 Added some methods to get geometry properities.
// 2015/08/10 Added methods corresponding to Xme* APIs in <Xm/TransferP.h>.
// 2016/03/27 Added sendExposeEvent method.
// 2016/09/12 Added getParent method.
#pragma once
#include <oz++/motif/IView.h>
#include <oz++/motif/Args.h>
#include <oz++/motif/Action.h>
#include <oz++/motif/Event.h>
#include <oz++/motif/Transducer.h>
#include <oz++/motif/CompoundString.h>
#include <oz++/motif/PlainString.h>
#include <oz++/motif/CompoundStringList.h>
#include <oz++/motif/Application.h>
#include <oz++/LinkedList.h>
#include <oz++/motif/RenderTable.h>
//2015/08/15
#include <Xm/TransferP.h>
namespace OZ {
class View :public IView {
private:
Boolean destructive;
Widget widget;
LinkedList callbackList;
LinkedList handlerList;
static void commonHandler(Widget widget, XtPointer client,
XEvent* xevent, Boolean* flag)
{
Event* event = (Event*)client;
if (event) {
event -> setXEvent(xevent);
event -> setOptionData((void*)flag);
event -> call(*event);
}
}
static void commonCallback(Widget widget, XtPointer client,
XtPointer callData)
{
Action* action = (Action*)client;
if (action) {
action -> setCallData(callData);
action -> call(*action);
}
}
protected:
XtEventHandler getCommonHandler()
{
return &View::commonHandler;
}
XtCallbackProc getCommonCallback()
{
return &View::commonCallback;
}
View()
{
destructive = True;
widget = NULL;
}
public:
//2015/01/22
View(Widget w)
{
widget = w;
nondestructive();
}
public:
~View()
{
if(widget && destructive) {
XtDestroyWidget(widget);
}
}
//2015/01/18
void nondestructive()
{
destructive = False;
}
virtual void addCallback(const char* name, CommonObject* object,
Callback callback, XtPointer data)
{
Action* action = new Action(this, object, callback, data, name);
XtAddCallback(getWidget(), name,
&View::commonCallback, action);
// 2014.10.17
callbackList.add(action);
}
virtual void addEventHandler(EventMask mask,
CommonObject* object, Handler handler, XtPointer data)
{
Event* event = new Event(this, object, handler, data);
XtAddEventHandler(getWidget(), mask, False,
&View::commonHandler, event);
handlerList.add(event);
}
virtual void addEventHandler(EventMask mask, Boolean nonmaskable,
CommonObject* object, Handler handler, XtPointer data)
{
Event* event = new Event(this, object, handler, data);
XtAddEventHandler(getWidget(), mask, nonmaskable,
&View::commonHandler, event);
handlerList.add(event);
}
virtual void addRawEventHandler(EventMask mask, Boolean nonmaskable,
CommonObject* object, Handler handler, XtPointer data)
{
Event* event = new Event(this, object, handler, data);
XtAddEventHandler(getWidget(), mask, nonmaskable,
&View::commonHandler, event);
handlerList.add(event);
}
void augmentTranslation(Application& applet, Transducer* transd,
CommonObject* object, Callback callback, XtPointer data)
{
char translation[256];
sprintf(translation, "%s: %s(%d,%s)",
transd->getEvents(), transd->getProc(),
transd->getId(), transd->getArgs());
Action* action = NULL;
applet.getAppContext()
->addAction(transd->getProc());
action = new Action(this, object, callback, data);
ActionProcTable::put(widget, action, transd->getId());
XtAugmentTranslations(widget,
XtParseTranslationTable(translation));
}
//2015/01/28 Modified to be virtual function
virtual void clear()
{
XClearWindow(XtDisplay(widget), XtWindow(widget));
}
void configure(Position x, Position y,
Dimension width, Dimension height, Dimension border)
{
XtConfigureWidget(widget, x, y, width, height, border);
}
//2015/02/20
Position x()
{
Position value = 0;
get(XmNx, (XtArgVal)&value);
return value;
}
Position y()
{
Position value = 0;
get(XmNy, (XtArgVal)&value);
return value;
}
Dimension width()
{
Dimension value = 0;
get(XmNwidth, (XtArgVal)&value);
return value;
}
Dimension height()
{
Dimension value = 0;
get(XmNheight, (XtArgVal)&value);
return value;
}
void get(Args* args)
{
XtGetValues(widget, args->getArgList(), args->count());
}
void get(const char* name, XmString* xms)
{
Args ar;
ar.set(name, (XtArgVal)xms);
XtGetValues(getWidget(), ar.getArgList(), 1);
}
void get(const char* name, CompoundString* cs)
{
if (cs) {
XmString xms;
Args ar;
ar.set(name, (XtArgVal)&xms);
XtGetValues(getWidget(), ar.getArgList(), 1);
cs -> set(xms);
}
}
void get(const char* name, CompoundString& cs)
{
XmString xms;
Args ar;
ar.set(name, (XtArgVal)&xms);
XtGetValues(getWidget(), ar.getArgList(), 1);
cs.set(xms);
}
//2015/01/23 Modified to be virtual
virtual void get(const char* name, XtArgVal value)
{
Args ar;
ar.set(name, value);
XtGetValues(getWidget(), ar.getArgList(), 1);
}
virtual void get(const char* name, Dimension& value)
{
Args ar;
ar.set(name, (XtArgVal)&value);
XtGetValues(getWidget(), ar.getArgList(), 1);
}
virtual void get(const char* name, Position& value)
{
Args ar;
ar.set(name, (XtArgVal)&value);
XtGetValues(getWidget(), ar.getArgList(), 1);
}
virtual void get(const char* name, int& value)
{
Args ar;
ar.set(name, (XtArgVal)&value);
XtGetValues(getWidget(), ar.getArgList(), 1);
}
//2017/05/10
XtArgVal get(const char* name)
{
XtArgVal value;
Args ar;
ar.set(name, (XtArgVal)&value);
XtGetValues(getWidget(), ar.getArgList(), 1);
return value;
}
Display* getDisplay() const
{
return XtDisplay(widget);
}
Widget getWidget() const
{
return widget;
}
Window getWindow() const
{
return XtWindow(widget);
}
virtual Boolean isDialog() const
{
return False;
}
Boolean isManaged() const
{
return XtIsManaged(widget);
}
Boolean isSensitive() const
{
return XtIsSensitive(widget);
}
virtual void manage()
{
XtManageChild(widget);
}
void map()
{
XtMapWidget(widget);
}
void move(Position x, Position y)
{
XtMoveWidget(widget, x, y);
}
void overrideTranslation(Application& applet, Transducer* transd,
CommonObject* object, Callback callback, XtPointer data)
{
char translation[256];
//sprintf(translation, "%s: (%d,%s)",
sprintf(translation, "#override %s: %s()",
//sprintf(translation, "%s: %s()",
transd->getEvents(),
transd->getProc());
//"commonActionProc");
//transd->getId(), transd->getArgs());
Action* action = NULL;
applet.getAppContext()
->addAction(transd->getProc());
action = new Action(this, object, callback, data);
ActionProcTable::put(widget, action, transd->getId());
XtTranslations parsed = XtParseTranslationTable(translation);
printf("Translation %s\n", translation);
if (parsed) {
XtOverrideTranslations(widget, parsed);
set(XmNtranslations, (XtArgVal)parsed);
} else {
printf("Failed to XtParseTranslationTable :%s", translation);
}
}
void realize()
{
XtRealizeWidget(widget);
}
virtual void resize(Position x, Position y, Dimension width, Dimension height, Dimension border)
{
XtMoveWidget(widget, x, y);
XtResizeWidget(widget, width, height, border);
}
virtual void reshape(int x, int y, int width, int height)
{
XtMoveWidget(widget, x, y);
XtResizeWidget(widget, width, height, 0);
}
virtual void resize(Dimension width, Dimension height)
{
XtResizeWidget(widget, width, height, 0);
}
void resize(Dimension width, Dimension height, Dimension border)
{
XtResizeWidget(widget, width, height, border);
}
void resize()
{
XtResizeWindow(widget);
}
void moveResize(int x, int y, unsigned int width, unsigned int height)
{
XMoveResizeWindow(getDisplay(), getWindow(), x, y,
width, height);
}
void removeCallback(const char* name, Action* action)
{
XtRemoveCallback(widget, (char*)name,
(XtCallbackProc)&View::commonCallback,
(XtPointer*)action);
callbackList.remove(action);
}
void removeAllCallbacks(const char* name)
{
XtRemoveAllCallbacks(widget, name);
// To do:
//remove actions corresponding to the name from callbackList.
}
void removeEventHandler(EventMask mask, Event* event)
{
XtRemoveEventHandler(widget, mask, False,
(XtEventHandler)&View::commonHandler,
(XtPointer)event);
}
void removeEventHandler(EventMask mask, Boolean nonmaskable,
Event* event)
{
XtRemoveEventHandler(widget, mask, nonmaskable,
(XtEventHandler)&View::commonHandler,
(XtPointer)event);
}
void set(Args* args)
{
XtSetValues(widget, args->getArgList(), args->count());
}
//2015/01/26
void set(Args& args)
{
XtSetValues(widget, args.getArgList(), args.count());
}
virtual void set(const char* name, XtArgVal value)
{
Args ar;
ar.set(name, value);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
void set(const char* name, int value)
{
Args ar;
ar.set(name, value);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
//2015/01/26
void set(const char* name, Pixel value)
{
Args ar;
ar.set(name, (XtArgVal)value);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
void set(const char* name, double value)
{
Args ar;
ar.set(name, value);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
void set(const char* name, Widget w)
{
Args ar;
ar.set(name, w);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
void set(const char* name, const char* string)
{
Args ar;
ar.set(name, string);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
void set(const char* name, CompoundString& cstring)
{
Args ar;
ar.set(name, cstring);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
void set(const char* name, View* view)
{
Args ar;
ar.set(name, view);
XtSetValues(getWidget(), ar.getArgList(), 1);
}
//2015/01/26
void set(const char* name, RenderTable* renderTable)
{
if (name && renderTable) {
Args ar;
ar.set(name, (XtArgVal)renderTable->get());
XtSetValues(getWidget(), ar.getArgList(), 1);
}
}
void setMappedWhenManaged(Boolean mapped)
{
XtSetMappedWhenManaged(widget, mapped);
}
void setSensitive(Boolean sensitive)
{
XtSetSensitive(widget, sensitive);
}
void enable()
{
setSensitive(True);
}
void disable()
{
setSensitive(False);
}
void setWidget(Widget widget1)
{
widget = widget1;
}
void translateCoords(Position x, Position y,
Position* rx, Position* ry)
{
XtTranslateCoords(widget, x, y, rx, ry);
}
void ungrabKey(KeyCode keycode, Modifiers modifiers)
{
XtUngrabKey(widget, keycode, modifiers);
}
void ungrabKeyboard(Time time)
{
XtUngrabKeyboard(widget, time);
}
void ungrabPointer(Time time)
{
XtUngrabPointer(widget, time);
}
void uninstallTranslations()
{
XtUninstallTranslations(widget);
}
void unmanage()
{
XtUnmanageChild(widget);
}
void unmap()
{
XtUnmapWidget(widget);
}
void update()
{
XClearArea(XtDisplay(widget), XtWindow(widget),
0, 0, 0, 0, True);
}
//2015/01/18
void processTraversal()
{
XmProcessTraversal(widget, XmTRAVERSE_CURRENT);
}
//RevertToParent, RevertToPointerRoot, or RevertToNone
void setInputFocus(int revert_to=RevertToNone, Time time=CurrentTime)
{
XSetInputFocus(getDisplay(), getWindow(), revert_to, time);
}
//2015/01/18
Screen* getScreen()
{
Display* display = getDisplay();
return ScreenOfDisplay(display, DefaultScreen(display));
}
Window getRootWindow()
{
Screen* scr = getScreen();
Display* display = getDisplay();
return RootWindow(display, XScreenNumberOfScreen(scr));
}
int grabPointer(Cursor cursor)
{
Window root = getRootWindow();
Window window = getWindow();
Display* display = getDisplay();
return XGrabPointer(
display, window, False,
ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, window, cursor, CurrentTime);
}
int ungrabPointer()
{
Display* display = getDisplay();
int rc = XUngrabPointer(display, CurrentTime);
return rc;
}
/*
typedef struct {
int x, y;
int width, height;
int border_width;
int depth;
Visual *visual;
Window root;
int class;
int bit_gravity;
int win_gravity;
int backing_store;
unsigned long backing_planes;
unsigned long backing_pixel;
Bool save_under;
Colormap colormap;
Bool map_installed;
int map_state;
long all_event_masks;
long your_event_mask;
long do_not_propagate_mask;
Bool override_redirect;
Screen *screen;
} XWindowAttributes;
*/
Status getAttributes(XWindowAttributes* attributes)
{
return XGetWindowAttributes(getDisplay(), getWindow(), attributes);
}
//2015/04/01
void changeAttributes(unsigned long valueMask, XSetWindowAttributes& attr)
{
XChangeWindowAttributes(getDisplay(), getWindow(), valueMask, &attr);
}
//2015/04/01
void changeColormap(Colormap colormap)
{
XSetWindowAttributes attr;
memset(&attr, 0, sizeof(attr));
attr.colormap = colormap;
XChangeWindowAttributes(getDisplay(), getWindow(), CWColormap, &attr);
}
int getDepth()
{
XWindowAttributes attributes;
XGetWindowAttributes(getDisplay(), getWindow(), &attributes);
return attributes.depth;
}
void queryMousePointer(int& root_x, int& root_y)
{
Display* display = getDisplay();
Window root = XDefaultRootWindow(display);
Window ret_root;
Window ret_child;
int win_x;
int win_y;
unsigned int mask;
XQueryPointer(display, root, &ret_root, &ret_child, &root_x, &root_y,
&win_x, &win_y, &mask);
}
void queryMousePointer(int& root_x, int& root_y, int& win_x, int& win_y)
{
Display* display = getDisplay();
Window root = XDefaultRootWindow(display);
Window ret_root;
Window ret_child;
unsigned int mask;
XQueryPointer(display, root, &ret_root, &ret_child, &root_x, &root_y,
&win_x, &win_y, &mask);
}
//2015/02/18
Pixel whitePixel()
{
return WhitePixel(getDisplay(), XDefaultScreen(getDisplay()) );
}
Pixel blackPixel()
{
return BlackPixel(getDisplay(), XDefaultScreen(getDisplay()) );
}
Pixel grayPixel()
{
return color("lightgray");
}
Colormap getDefaultColormap()
{
return DefaultColormap(getDisplay(), XDefaultScreen(getDisplay()));
}
Pixel colorPixel(const char* name)
{
XColor color;
XColor exact;
XAllocNamedColor(getDisplay(), getDefaultColormap(), name, &color, &exact);
return color.pixel;
}
Pixel color(const char* name)
{
XColor color;
XColor exact;
XAllocNamedColor(getDisplay(), getDefaultColormap(), name, &color, &exact);
return color.pixel;
}
Status sendEvent(Boolean propagate, long event_mask, XEvent* event_send)
{
return XSendEvent(getDisplay(), getWindow(), propagate, event_mask, event_send);
}
void mapRaisedWindow()
{
XMapRaised(getDisplay(), getWindow());
}
void mapSubWindows()
{
XMapSubwindows(getDisplay(), getWindow());
}
void unmapSubWindows()
{
XUnmapSubwindows(getDisplay(), getWindow());
}
void raiseWindow()
{
XRaiseWindow(getDisplay(), getWindow());
}
void lowerWindow()
{
XLowerWindow(getDisplay(), getWindow());
}
void changeWindowAttributes(unsigned long valuemask, XSetWindowAttributes *attributes)
{
XChangeWindowAttributes(getDisplay(), getWindow(), valuemask, attributes);
}
//2015/03/27
virtual void updateView()
{
}
//2015/03/27
virtual void updateModel(CommonObject* object)
{
}
//2015/03/27
void flush()
{
XFlush(getDisplay());
}
//2015/08/10
Boolean primarySource(Time time)
{
return XmePrimarySource(getWidget(), time);
}
Boolean namedSource(Atom atom, Time time)
{
return XmeNamedSource(getWidget(), atom, time);
}
Boolean scondarySource(Time time)
{
return XmeSecondarySource(getWidget(), time);
}
void secondaryTransfer(Atom atom, XtEnum xtEnum, Time time)
{
XmeSecondaryTransfer(getWidget(), atom, xtEnum, time);
}
Boolean clipboardSource(XtEnum xtEnum, Time time)
{
return XmeClipboardSource(getWidget(), xtEnum, time);
}
Widget dragSource(XtPointer data, XEvent* xev, Args& args)
{
return XmeDragSource(getWidget(), data, xev, args.getArgList(),
args.count());
}
Boolean primarySink(XtEnum xtEnum, XtPointer data, Time time)
{
return XmePrimarySink(getWidget(), xtEnum, data, time);
}
Boolean namedSink(Atom atom, XtEnum xtEnum, XtPointer data, Time time)
{
return XmeNamedSink(getWidget(), atom, xtEnum, data, time);
}
Boolean secondarySink(Time time)
{
return XmeSecondarySink(getWidget(), time);
}
Boolean clipboardSink(XtEnum xtEnum, XtPointer data)
{
XmeClipboardSink(getWidget(), xtEnum, data);
}
void dropSink(Args& args)
{
return XmeDropSink(getWidget(), args.getArgList(),
args.count());
}
Atom* standardTargets(int target, int* targets)
{
return XmeStandardTargets(getWidget(), target, targets);
}
void standardConvert(XtPointer data, XmConvertCallbackStruct* cbs)
{
XmeStandardConvert(getWidget(), data, cbs);
}
Atom getEncodingAtom()
{
return XmeGetEncodingAtom(getWidget());
}
//2016/03/27
void sendExposeEvent()
{
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.type = Expose;
xev.xexpose.window = this->getWindow();
this -> sendEvent(false, ExposureMask, &xev);
this -> flush(); //This may be needed to update the view on a multithreaded
//application.
}
void sendRenderRequest()
{
sendExposeEvent();
}
void sendFocusInEvent()
{
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.type = FocusIn;
xev.xfocus.window = this->getWindow();
this -> sendEvent(false, FocusChangeMask, &xev);
this -> flush(); //This may be needed to update the view
}
void sendConfigureEvent()
{
XEvent e;
memset(&e, 0, sizeof(e));
Display* display = getDisplay();
Window window = getWindow();
Dimension width;
Dimension height;
get(XmNwidth, (XtArgVal)&width);
get(XmNheight, (XtArgVal)&height);
e.type = ConfigureNotify;
e.xconfigure.display = getDisplay();
//e.xconfigure.event = window;
e.xconfigure.window = window;
e.xconfigure.x = 0;
e.xconfigure.y = 0;
e.xconfigure.width = width;
e.xconfigure.height = height;
e.xconfigure.border_width = 0;
this->sendEvent(False, StructureNotifyMask, &e);
this->flush(); //This may be needed to update the view
}
//2016/09/15
virtual View* getParent()
{
return NULL;
}
//2016/09/15
operator Widget()
{
return widget;
}
virtual void display()
{
}
};
}