[comp.sources.sun] v01i081: Paneledit: interactive editor for SunView panels

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (11/29/89)

Submitted-by: mbp@lakisis.umd.edu (Mark Phillips)
Posting-number: Volume 1, Issue 81
Archive-name: paneledit


     Here is a piece of code which I call "paneledit" that can save
SunView programmers hours of development time.  It allows you to
reposition any panel item in your program interactively.  It is not a
standalone program, but rather can be incorporated into any SunView
program at any time by simply adding one line to the program's source
code and recompiling.  It allows you to switch between the program's
normal operational mode and a special "editing" mode, in which you can
use the mouse to drag panel items around and find out their new x,y
coordinates.  You can switch modes as often as you like.

     Paneledit incorporates a procedure called "move_item" by Chuck
Musciano (posted to Sun-Spots in July '88) in a way that frees you
from having to explicitly change your code to reference move_item.
You just add one line to your program, and poof!, you can drag panel
items around to your heart's content, without interfering with the
normal functionality of the program.

     The code, instructions, and a short example program are in
the shar file below.  Enjoy!

Mark Phillips			  mbp@lakisis.umd.edu
Department of Mathematics         (301) 454-6550
University of Maryland
College Park, Maryland 20742
USA            
----------------------------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  . ./Makefile ./README ./myprog.c ./paneledit.c MANIFEST
# Wrapped by mbp@lakisis on Tue Oct 17 09:57:08 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./Makefile'\"
else
echo shar: Extracting \"'./Makefile'\" \(411 characters\)
sed "s/^X//" >'./Makefile' <<'END_OF_FILE'
X# $Id: Makefile,v 1.0 89/10/01 17:00:22 mbp Exp $
X#
X#  makefile for "paneledit.o" and example program "myprog"
X#
X#  type "make" to just make paneledit.o
X#
X#  type "make myprog" to make myprog
X#
X
Xpaneledit.o:		paneledit.c
X	cc -c -o paneledit.o paneledit.c
X
Xmyprog:			myprog.o paneledit.o
X	cc -o myprog myprog.o paneledit.o \
X		-lm -lsuntool -lsunwindow -lpixrect
X
Xmyprog.o:		myprog.c
X	cc -c -o myprog.o myprog.c
END_OF_FILE
if test 411 -ne `wc -c <'./Makefile'`; then
    echo shar: \"'./Makefile'\" unpacked with wrong size!
fi
# end of './Makefile'
fi
if test -f './README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./README'\"
else
echo shar: Extracting \"'./README'\" \(5637 characters\)
sed "s/^X//" >'./README' <<'END_OF_FILE'
X			       PANELEDIT
X
X			      VERSION 1.0
X			    February 2, 1989
X
X     Mark Phillips                     Chuck Musciano
X     Department of Mathematics         Advanced Technology Department
X     University of Maryland            Harris Corporation
X     College Park, Maryland 20742      PO Box 37, MS 3A/1912
X     (301) 454-2693                    Melbourne, FL 32902
X     ARPA: mbp@lakisis.umd.edu         (407) 727-6131
X                                       ARPA: chuck@trantor.harris-atd.com
X
X     Everything except procedure "move_item":
X	Copyright 1989 by Mark Phillips and the University of Maryland
X
X     Procedure "move_item":
X	Copyright 1988 by Chuck Musciano and Harris Corporation
X
X     Permission to use, copy, modify, and distribute this software and
X     its  documentation for  any  purpose and without   fee  is hereby
X     granted, provided that the above copyright  notices appear in all
X     copies and that both those copyright notices and  this permission
X     notice appear in supporting documentation, and that the  names of
X     Mark Phillips, the  University of Maryland,  Chuck Musciano,  and
X     Harris   Corporation not  be  used in  advertising  or  publicity
X     pertaining to  distribution  of the   software without  specific,
X     written prior  permission.   Mark   Phillips, the  University  of
X     Maryland, Chuck  Musciano,    and  Harris  Corporation  make   no
X     representations about the suitability   of this software for  any
X     purpose.   It  is   provided "as  is"  without express or implied
X     warranty.
X
X*   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
X
X			      INSTRUCTIONS
X
X     Paneledit is a "module" which allows you to use the mouse to move
Xpanel items (buttons, sliders, messages, text fields, etc) around in a
XSunView panel.  It can be incorporated into any SunView program at any
Xtime --- it requires a minimal amount of effort to install into or
Xremove from a program, which makes it ideal for program development.
XIt is very useful during the design stages of a program because it
Xallows you to reposition panel items at any time, without having to
Xmake lots of experimental changes to your source code.
X
X     Paneledit consists of the file "paneledit.c".  To use it, just add
Xthe single line
X
X		paneledit_init(base_frame);
X
Xto you source code immediately before your window_main_loop(base_frame)
Xcall (where base_frame is, of course, the handle of your program's main
Xframe).  Then link paneledit.o in with your program.
X
X     When your program starts, a (very small) separate frame will appear
Xalong with your program's frame(s).  This frame has one panel cycle item
Xlabeled "Panel Editing".  Your program will function normally as long as
Xthis cycle is "Off", which is its initial state.  Switching it to "On"
Xputs your program in an "editing" mode.  While in editing mode, you can
Xuse the mouse to reposition any panel item in your program.  To do this,
Xsimply position the mouse cursor over the desired item, and hold down
Xthe left mouse button to drag the item horizontally, or the middle mouse
Xbutton to drag it vertically.  Clicking the right mouse button causes
Xthe item to report it's x,y location (in the coordinate system of its
Xpanel) on stdout.  To return to normal mode, switch the "Panel Editing"
Xcycle back to "Off".  You can switch into and out of editing mode as
Xoften as you like.
X
XSend all bugs, comments, questions, and suggestions to:
X
X            Mark Phillips
X            Department of Mathematics
X            University of Maryland
X            College Park, Maryland 20742
X            (301) 454-6550
X            mbp@lakisis.umd.edu
X
X
X				 NOTES
X
X  1. The program "myprog.c" is a do-nothing sample program which
X     illustrates the use of paneledit.  To build it (and paneledit.o),
X     type "make myprog".
X  
X  2. The paneledit frame is supposed to appear on the screen immediately
X     below your program's main frame.  If your main frame is programmed
X     to come up with its bottom edge close to the bottom of the screen,
X     the paneledit frame may not be visible.
X  
X  3. If you close the paneledit frame by picking "Done" from it's frame
X     menu, there is no way to get it back without restarting your
X     program.
X  
X  4. You cannot "edit" the "Panel Editing" cycle in the paneledit frame.
X
X  5. Paneledit can edit only one "window tree".  If your program has
X     multiple base frames, you can attach paneledit to only one of them
X     at a time.
X  
X  6. Paneledit uses uses dynamically allocated memory to store the
X     original event procs for all your panel items when in editing mode.
X     If it runs out of memory when entering editing mode, it dies very
X     ungracefully, taking your program with it.
X  
X  7. When you reposition an item with paneledit, the new position is not
X     permanently part of your program.  In order for it to be permanent,
X     you obviously have to change the x,y coordinates in your source
X     code and recompile.  The right mouse button allows you to find out
X     the item's new coordinates so that you can make this change easily.
X     One way to enhance paneledit might be to have it record all your
X     items' locations in a file which would be incorporated into your
X     source code automatically.  If anyone has any suggestions of how to
X     do this, I would appreciate hearing about them.
X
X  8. This version of paneledit was written on a Sun 3 running version
X     3.5 of SunOS.  I have not tested it on other systems.
X
X				 FILES
X
X	README:		this file
X	paneledit.c:	source code
X	myprog.c:	example program
X	Makefile:	makefile for paneledit.o and myprog
END_OF_FILE
if test 5637 -ne `wc -c <'./README'`; then
    echo shar: \"'./README'\" unpacked with wrong size!
fi
# end of './README'
fi
if test -f './myprog.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./myprog.c'\"
else
echo shar: Extracting \"'./myprog.c'\" \(1915 characters\)
sed "s/^X//" >'./myprog.c' <<'END_OF_FILE'
X/* $Id: myprog.c,v 1.0 89/10/01 17:00:27 mbp Exp $
X *
X * myprog.c: SunView program to illustrate use of paneledit
X *
X * usage: myprog [generic Suntools window arguments]
X */
X
X#include <stdio.h>
X#include <suntool/sunview.h>
X#include <suntool/panel.h>
X
Xstatic Frame base_frame;
Xstatic Panel_item button1,button2, message;
Xstatic int button_event_proc(), quit_program();
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X  initialize_windows(argc,argv);
X  paneledit_init(base_frame);
X  window_main_loop(base_frame);
X}
X
Xstatic int
Xinitialize_windows(argc,argv)
Xint argc;
Xchar **argv;
X{
X  static Panel panel;
X
X  base_frame =
X    window_create(NULL, FRAME,
X		  FRAME_LABEL, "Myprog",
X		  FRAME_ARGS, argc, argv,
X		  0);
X
X  panel =
X    window_create(base_frame, PANEL,
X		  WIN_WIDTH, 300,
X		  WIN_HEIGHT, 300,
X		  0);
X
X  button1 = 
X    panel_create_item(panel, PANEL_BUTTON,
X		      PANEL_LABEL_IMAGE,
X		        panel_button_image(panel, "Button 1", 0, 0),
X		      PANEL_NOTIFY_PROC, button_event_proc,
X		      0);
X
X  button2 =
X    panel_create_item(panel, PANEL_BUTTON,
X		      PANEL_LABEL_IMAGE,
X		        panel_button_image(panel, "Button 2", 0, 0),
X		      PANEL_NOTIFY_PROC, button_event_proc,
X		      0);
X
X  panel_create_item(panel, PANEL_BUTTON,
X		    PANEL_LABEL_IMAGE,
X		      panel_button_image(panel, "Quit", 0, 0),
X		    PANEL_NOTIFY_PROC, quit_program,
X		    0);
X
X  message =
X    panel_create_item(panel, PANEL_MESSAGE,
X		      PANEL_LABEL_STRING, "This is a messge item",
X		      0);
X
X  window_fit(base_frame);
X}
X
Xstatic int
Xbutton_event_proc(item, event)
X     Panel_item item;
X     Event *event;
X{
X  char buf[30];
X
X  if (item==button1) {
X    sprintf(buf,"You picked Button 1");
X  }
X  else if (item==button2) {
X    sprintf(buf,"You picked Button 2");
X  }
X  else {
X    sprintf(buf,"Unknown button!!");
X  }
X
X  panel_set(message, PANEL_LABEL_STRING, buf, 0);
X}
X
Xstatic int
Xquit_program()
X{
X  window_done(base_frame);
X}
END_OF_FILE
if test 1915 -ne `wc -c <'./myprog.c'`; then
    echo shar: \"'./myprog.c'\" unpacked with wrong size!
fi
# end of './myprog.c'
fi
if test -f './paneledit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./paneledit.c'\"
else
echo shar: Extracting \"'./paneledit.c'\" \(7473 characters\)
sed "s/^X//" >'./paneledit.c' <<'END_OF_FILE'
X/* $Id: paneledit.c,v 1.0 89/10/01 17:00:29 mbp Exp $
X *
X * paneledit.c               version 1.0             February 2, 1989
X *
X * Allows dynamic repositioning of all panel items in all panels
X *
X * Authors:
X *                                      procedure move_item() by:
X *     Mark Phillips                    Chuck Musciano
X *     Department of Mathematics        Advanced Technology Department
X *     University of Maryland           Harris Corporation
X *     College Park, Maryland 20742     PO Box 37, MS 3A/1912
X *     (301) 454-2693                   Melbourne, FL 32902
X *     ARPA: mbp@lakisis.umd.edu        (407) 727-6131
X *                                      ARPA: chuck@trantor.harris-atd.com
X *
X * Everything except procedure "move_item":
X *      Copyright 1989 by Mark Phillips and the University of Maryland
X *
X * Procedure "move_item":
X *      Copyright 1988 by Chuck Musciano and Harris Corporation
X *
X * Permission to use, copy, modify, and  distribute this software and
X * its  documentation for  any purpose   and without   fee is  hereby
X * granted, provided that  the above copyright  notices appear in all
X * copies and that both  those  copyright notices and this permission
X * notice appear in supporting  documentation, and  that the names of
X * Mark Phillips, the  University  of Maryland,  Chuck Musciano,  and
X * Harris  Corporation  not be   used  in advertising   or  publicity
X * pertaining  to   distribution of   the software without  specific,
X * written prior   permission.   Mark Phillips,   the   University of
X * Maryland,  Chuck   Musciano,   and  Harris  Corporation  make   no
X * representations about the  suitability  of  this software  for any
X * purpose.   It is  provided  "as  is" without  express   or implied
X * warranty.
X */
X
X#include <stdio.h>
X#include <suntool/sunview.h>
X#include <suntool/panel.h>
X
Xtypedef	struct save_block_tag {
X  caddr_t	client_data;
X  caddr_t	event_proc;
X} Save_block;
X
Xstatic Frame base_frame;
Xstatic Frame edit_frame;
Xstatic Panel edit_panel;
Xstatic Panel_item edit_cycle;
Xstatic int toggle_edit(), move_item();
X
X#define		NO_DRAG		0
X#define		DRAG_X		1
X#define		DRAG_Y		2
Xstatic int dragging = NO_DRAG;
X
Xstatic int editing = 0;
X
X/*-----------------------------------------------------------------------
X * Function:	paneledit_init
X * Description:	Set up editing of SunView panels
X * Args  IN:	frame: handle of frame
X * Returns:	success status: 0 for success, 1 for failure
X * Notes:	All panel items in all subwindows of frame can be edited.
X */
Xpaneledit_init(frame)
XFrame frame;
X{
X  int h;
X
X  base_frame = frame;
X
X  edit_frame =
X    window_create(base_frame, FRAME,
X		  FRAME_LABEL, "paneledit - 1.0",
X		  FRAME_SHOW_LABEL, TRUE,
X		  0);
X
X  edit_panel = window_create(edit_frame, PANEL,0);
X  edit_cycle =
X    panel_create_item(edit_panel, PANEL_CYCLE,
X		      PANEL_LABEL_STRING, "Panel Editing ",
X		      PANEL_CHOICE_STRINGS, "Off", "On", 0,
X		      PANEL_NOTIFY_PROC, toggle_edit,
X		      0);
X  window_fit(edit_panel);
X  window_fit(edit_frame);
X  window_set(edit_frame,
X	     WIN_X, 0,
X	     WIN_Y, (int)window_get(base_frame, WIN_HEIGHT),
X	     WIN_SHOW, TRUE,
X	     0);
X}
X
X/*-----------------------------------------------------------------------
X * Function:	toggle_edit
X * Description:	toggle whether panel items are being edited
X * Notes:	this is the event procedure for the editing cycle item
X */
Xstatic int
Xtoggle_edit()
X{
X  /* We toggle the editing state and apply new state to window tree */
X  editing = !editing;
X  set_editing_in_window(base_frame, editing);
X}
X
X/*-----------------------------------------------------------------------
X * Function:	set_editing_in_window
X * Description:	turn editing on or off in a specific window
X * Args  IN:	window: the window's handle
X *		edit: 0 to turn editing off, 1 to turn it on
X * Returns:	nothing
X * Notes:	This procedure calls itself to operate on the entire
X *		window tree with window as root
X */
Xstatic int
Xset_editing_in_window(window, edit)
X     Window window;
X     int edit;
X{
X  int winno;
X  Window subwindow;
X
X  winno = 0;
X  do {
X    /* Get next subwindow */
X    subwindow = (Window)window_get(window, FRAME_NTH_WINDOW, winno);
X    if (subwindow!=NULL) {
X      /* Make sure this is not the edit frame! */
X      if (subwindow != edit_frame) {
X	switch ( (Window_type)(window_get(subwindow,WIN_TYPE)) ) {
X	case FRAME_TYPE:
X	  set_editing_in_window(subwindow, edit);
X	  break;
X	case PANEL_TYPE:
X	  set_editing_in_panel(subwindow, edit);
X	  break;
X	default:
X	  /* do nothing */
X	  break;
X	}
X      }
X    }
X    ++winno;
X  } while (subwindow != NULL);
X}
X
X/*-----------------------------------------------------------------------
X * Function:	set_editing_in_panel
X * Description:	turn editing on or off for all items in a panel
X * Args  IN:	panel: the panel's handle
X *		edit: 0 to turn editing off, 1 to turn it on
X * Returns:	nothing
X */
Xstatic int
Xset_editing_in_panel(panel, edit)
X     Panel panel;
X     int edit;
X{
X  Panel_item item;
X  Save_block *b;
X
X  /* Loop thru each item in this panel */
X  panel_each_item(panel, item) {
X
X    if (edit) {
X
X      /* allocate a Save_block for item's current info */
X      b = (Save_block*)malloc(sizeof(Save_block));
X      if (b == NULL) {
X	printf(stderr, "Sorry, no memory left for panel_edit !!\n");
X	exit(1);
X      }
X      b->client_data = (caddr_t)panel_get(item, PANEL_CLIENT_DATA);
X      b->event_proc = (caddr_t)panel_get(item, PANEL_EVENT_PROC);
X
X      /* Store pointer to this Save_block as item's new client data */
X      panel_set(item, PANEL_CLIENT_DATA, b, 0);
X
X      /* For editing, use move_item as event proc */
X      panel_set(item, PANEL_EVENT_PROC, move_item, 0);
X    }
X
X    else {
X
X      /* restore previous event proc and client data */
X      b = (Save_block*)panel_get(item, PANEL_CLIENT_DATA);
X      panel_set(item, PANEL_EVENT_PROC, b->event_proc, 0);
X      panel_set(item, PANEL_CLIENT_DATA, b->client_data, 0);
X
X      /* free up the Save_block */
X      free(b);
X    }
X
X  } panel_end_each;
X
X}
X
X/*-----------------------------------------------------------------------
X * Function:	move_item
X * Description:	A notify proc which allows items to move about and then
X *		  report their position.
X * Args  IN:	item: item's handle
X *		event: event which caused notification
X * Returns:	nothing
X * Notes: 	Copyright 1988 by Chuck Musciano and Harris Corporation
X */
Xstatic int
Xmove_item(item, event)
X     Panel_item	item;
X     Event	*event;
X{
X  static int old_x, old_y;
X  static Panel_item old_item;
X
X  if (event_id(event) == MS_LEFT)
X    if (event_is_down(event)) {
X      dragging = DRAG_X;
X      old_x = event_x(event);
X      old_item = item;
X    }
X    else
X      dragging = NO_DRAG;
X  else if (event_id(event) == MS_MIDDLE)
X    if (event_is_down(event)) {
X      dragging = DRAG_Y;
X      old_y = event_y(event);
X      old_item = item;
X    }
X    else
X      dragging = NO_DRAG;
X  else if (event_id(event) == MS_RIGHT && event_is_down(event))
X    printf("%5d %5d\n", panel_get(item, PANEL_ITEM_X),
X	   panel_get(item, PANEL_ITEM_Y));
X  else if (event_id(event) == LOC_DRAG)
X    if (dragging == DRAG_X) {
X      panel_set(old_item, PANEL_ITEM_X,
X		panel_get(item, PANEL_ITEM_X) + event_x(event) - old_x, 0);
X      old_x = event_x(event);
X    }
X    else if (dragging == DRAG_Y) {
X      panel_set(old_item, PANEL_ITEM_Y,
X		panel_get(item, PANEL_ITEM_Y) + event_y(event) - old_y, 0);
X      old_y = event_y(event);
X    }
X    else
X      panel_default_handle_event(item, event);
X}
END_OF_FILE
if test 7473 -ne `wc -c <'./paneledit.c'`; then
    echo shar: \"'./paneledit.c'\" unpacked with wrong size!
fi
# end of './paneledit.c'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(300 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X .                          1	
X ./Makefile                 1	
X ./README                   1	
X ./myprog.c                 1	
X ./paneledit.c              1	
X MANIFEST                   1	This shipping list
END_OF_FILE
if test 300 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    echo "Now read the file README"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0