Blob Blame History Raw
/* $XConsortium: autopopups.c /main/5 1995/07/15 20:45:56 drk $ */
/*
 * Motif
 *
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
 *
 * These libraries and programs are free software; you can
 * redistribute them and/or modify them under the terms of the GNU
 * Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * These libraries and programs are distributed in the hope that
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with these librararies and programs; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301 USA
 */
/*
 * HISTORY
 */

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/IntrinsicP.h>
#include <X11/CompositeP.h>
#include <Xm/XmP.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/LabelG.h>
#include <Xm/SeparatoG.h>
#include <Xm/RowColumn.h>
#include <Xm/BulletinB.h>
#include <Xm/DrawingA.h>

XtAppContext context;
#define APP_CLASS "AutomaticPopups"

Widget exitpb;

void QuitAppl(Widget, char *, XmPushButtonCallbackStruct *);
void ExposeCB(Widget, char *, XmDrawingAreaCallbackStruct *);
void ButtonEventHandler(Widget, XtPointer, XEvent*);
void PopupHandlerCB(Widget, XtPointer, XmPopupHandlerCallbackStruct *);
void addButton(Widget, char*);
void addChildren(Widget, char*);

int circlex, circley, circled;
int rectx, recty, recth, rectw;

Widget	popup1, popup2, popup3, popup4, popup5;

int main(int argc, char **argv)
{
  Widget        shell;
  Widget        frame1, frame2;
  Widget	da1, da2;
  Widget	btn1, btn2, label1, label2, btn3, sbtn1;
  Widget	explain;
  Arg		args[10];
  int		count;
  XmString	str, tmp1, tmp2;

  shell     = XtVaAppInitialize(&context, APP_CLASS, NULL, 0, &argc, argv,
				NULL, 0);

  frame1 = XmCreateFrame(shell, "outerframe", NULL, 0);
  XtManageChild(frame1);

  count = 0;
  XtSetArg(args[count], XmNpopupEnabled, XmPOPUP_AUTOMATIC_RECURSIVE); count++;
  popup1 = XmCreatePopupMenu(frame1, "popupOF", args, count);

  addChildren(popup1, "OuterFrameMenu");

  str = XmStringCreateLocalized("OuterFrame");
  count = 0;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNframeChildType, XmFRAME_TITLE_CHILD); count++;
  label1 = XmCreateLabel(frame1, "label1", args, count);
  XtManageChild(label1);
  XmStringFree(str);

  count = 0;
  XtSetArg(args[count], XmNheight, 500); count++;
  XtSetArg(args[count], XmNwidth, 500); count++;
  XtSetArg(args[count], XmNframeChildType, XmFRAME_WORKAREA_CHILD); count++;
  XtSetArg(args[count], XmNresizePolicy, XmRESIZE_NONE); count++;
  da1 = XmCreateDrawingArea(frame1, "da1", args, count);
  XtManageChild(da1);

  count = 0;
  XtSetArg(args[count], XmNx, 100); count++;
  XtSetArg(args[count], XmNy, 100); count++;
  frame2 = XmCreateFrame(da1, "innerframe", args, count);
  XtManageChild(frame2);

  count = 0;
  XtSetArg(args[count], XmNpopupEnabled, XmPOPUP_AUTOMATIC_RECURSIVE); count++;
  popup2 = XmCreatePopupMenu(frame2, "popupIF", args, count);

  addChildren(popup2, "InnerFrameMenu");
  addButton(popup2, "Make me different");

  str = XmStringCreateLocalized("InnerFrame");
  count = 0;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNframeChildType, XmFRAME_TITLE_CHILD); count++;
  label2 = XmCreateLabel(frame2, "label2", args, count);
  XtManageChild(label2);
  XmStringFree(str);

  count = 0;
  XtSetArg(args[count], XmNheight, 300); count++;
  XtSetArg(args[count], XmNwidth, 300); count++;
  XtSetArg(args[count], XmNframeChildType, XmFRAME_WORKAREA_CHILD); count++;
  XtSetArg(args[count], XmNresizePolicy, XmRESIZE_NONE); count++;
  da2 = XmCreateDrawingArea(frame2, "da2", args, count);
  XtManageChild(da2);
  XtAddCallback(da2, XmNexposeCallback, (XtCallbackProc) ExposeCB, NULL);
  XtAddCallback(da2, XmNpopupHandlerCallback, 
		(XtCallbackProc) PopupHandlerCB, NULL);

  count = 0;
  str = XmStringCreateLocalized(
	"Click Button3 anywhere to cause a popup menu");
  tmp1 = XmStringConcat(str, XmStringSeparatorCreate());
  XmStringFree(str);
  tmp2 = XmStringCreateLocalized(
         "to be posted.  Note that the posted menu");
  str = XmStringConcat(tmp1, tmp2);
  XmStringFree(tmp1);
  XmStringFree(tmp2);
  tmp1 = XmStringConcat(str, XmStringSeparatorCreate());
  XmStringFree(str);
  tmp2 = XmStringCreateLocalized(
         "differs depending on where you click.");
  str = XmStringConcat(tmp1, tmp2);
  XmStringFree(tmp1);
  XmStringFree(tmp2);

  XtSetArg(args[count], XmNx, 10); count++;
  XtSetArg(args[count], XmNy, 200); count++;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNalignment, XmALIGNMENT_BEGINNING); count++;
  explain = XmCreateLabelGadget(da2, "Explain", args, count);
  XtManageChild(explain);
  XmStringFree(str);

  circlex = 40; circley = 120; circled = 30;
  rectx = 80; recty = 120; recth = 30; rectw = 60;

  str = XmStringCreateLocalized("Quit");
  count = 0;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNx, 40); count++;
  XtSetArg(args[count], XmNy, 40); count++;
  btn1 = XmCreatePushButton(da2, "pb1", args, count);
  XtManageChild(btn1);
  XtAddCallback(btn1, XmNactivateCallback, 
		(XtCallbackProc) QuitAppl, NULL);

  str = XmStringCreateLocalized("Another Button With no Menu");
  count = 0;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNx, 40); count++;
  XtSetArg(args[count], XmNy, 80); count++;
  btn3 = XmCreatePushButton(da2, "pb3", args, count);
  XtManageChild(btn3);

  count = 0;
  XtSetArg(args[count], XmNpopupEnabled, XmPOPUP_AUTOMATIC); count++;
  popup4 = XmCreatePopupMenu(btn1, "popupBtn1", args, count);

  addChildren(popup4, "SharedMenu");
  addButton(popup4, "Do something more");
  addButton(popup4, "What else?");


  str = XmStringCreateLocalized("PushMe");
  count = 0;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNx, 40); count++;
  XtSetArg(args[count], XmNy, 40); count++;
  btn2 = XmCreatePushButton(da1, "pb2", args, count);
  XtManageChild(btn2);

  str = XmStringCreateLocalized("I share a menu");
  count = 0;
  XtSetArg(args[count], XmNlabelString, str); count++;
  XtSetArg(args[count], XmNx, 240); count++;
  XtSetArg(args[count], XmNy, 40); count++;
  sbtn1 = XmCreatePushButton(da1, "sharepb1", args, count);
  XtManageChild(sbtn1);

  /* Associate a menu with this button */
  XmAddToPostFromList(popup4, sbtn1);

  count = 0;
  XtSetArg(args[count], XmNpopupEnabled, XmPOPUP_AUTOMATIC); count++;
  popup3 = XmCreatePopupMenu(btn2, "popupBtn2", args, count);

  addChildren(popup3, "Button2Menu");
  addButton(popup3, "Do something more");
  
  count = 0;
  XtSetArg(args[count], XmNpopupEnabled, True); count++;
  popup4 = XmCreatePopupMenu(da2, "PopupObjects1", args, count);

  addChildren(popup4, "ObjectMenu");
  addButton(popup4, "Flip");
  addButton(popup4, "Size");
  addButton(popup4, "Stretch");
  
  XtRealizeWidget(shell);

  XtAppMainLoop(context);

  return 0;    /* make compiler happy */
}


void 
QuitAppl(Widget w, char *i, XmPushButtonCallbackStruct *e)
{
  exit(0);
}

void 
addChildren(Widget popup, char* label)
{
  XmString str;
  Arg args[2];
  Widget child;

  str = XmStringCreateLocalized(label);
  XtSetArg(args[0], XmNlabelString, str);
  child = XmCreateLabelGadget(popup, "Title", args, 1);
  XtManageChild(child);
  XmStringFree(str);

  child = XmCreateSeparatorGadget(popup, "Sep", NULL, 0);
  XtManageChild(child);

  addButton(popup, "Cut");
  addButton(popup, "Copy");
  addButton(popup, "Paste");

}

void 
addButton(Widget parent, char* label) 
{
  Widget ch;
  XmString str;
  Arg args[2];

  str = XmStringCreateLocalized(label);
  XtSetArg(args[0], XmNlabelString, str);
  ch = XmCreatePushButtonGadget(parent, label, args, 1);
  XtManageChild(ch);
  XmStringFree(str);

}

GC drawGC = NULL;

void 
ExposeCB(Widget da, char *ig, XmDrawingAreaCallbackStruct *cbs)
{
  Arg args[2];
  XGCValues gcv;
  Pixel fg;
  Pixel bg;

  if (drawGC == NULL) {
    XtSetArg (args[0], XmNforeground, &fg);
    XtSetArg (args[1], XmNbackground, &bg);
    XtGetValues (da, args, 2);
    gcv.foreground = fg;
    gcv.background = bg;
    gcv.line_width = 2;
    drawGC = XtGetGC (da, GCForeground | GCBackground | GCLineWidth, &gcv);
  }

  XDrawArc(XtDisplay(da), XtWindow(da), drawGC,
	   circlex, circley, circled, circled, 
	   0, (360 * 64));
  XDrawRectangle(XtDisplay(da), XtWindow(da), drawGC, 
		 rectx, recty, rectw, recth);

}

void 
PopupHandlerCB(Widget da, XtPointer ignore, XmPopupHandlerCallbackStruct *phcs)
{
  int radius;
  int dx, dy;
  XButtonEvent *bevent = (XButtonEvent *) phcs -> event;
  int eventx, eventy;
  Position wox, woy;

  /* Translate event coordinates to this widget */
  /* First get origin of this widget */
  XtTranslateCoords(da, 0, 0, &wox, &woy);

  /* Now calculate relative offset */
  eventx = bevent -> x_root - wox;
  eventy = bevent -> y_root - woy;
  
  /* Check for hit in circle or rectangle to post special 
     menus */

  dx = eventx - rectx;
  dy = eventy - recty;

  if (dx > 0 && dx < rectw &&
      dy > 0 && dy < recth) {
    phcs -> menuToPost = popup4;
    return;
  }

  dx = eventx - circlex;
  dy = eventy - circley;

  dx -= circled / 2;
  dy -= circled / 2;

  radius = (dx * dx) + (dy * dy);

  if (radius < ((circled * circled) / 4))
    phcs -> menuToPost = popup4;
}