/* * File: gobjects.h * ---------------- * This interface exports a hierarchy of graphical shapes based on * the model developed for the ACM Java Graphics. * */ /*************************************************************************/ /* Stanford Portable Library */ /* Copyright (C) 2013 by Eric Roberts */ /* */ /* This program is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation, either version 3 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program. If not, see . */ /*************************************************************************/ #ifndef _gobjects_h #define _gobjects_h #include "cslib.h" #include "generic.h" #include "gtypes.h" #include "vector.h" #ifndef _gwindow_h typedef struct GWindowCDT *GWindow; /* * Type: GObject * ------------- * This type represents an abstract type that unifies the set of all * graphics objects. As with an abstract class in an object-oriented * language, it is not legal to create a GObject directly. * Graphical objects are created instead by calling the constructor for * one of the concrete subclasses, as follows: * * * *

Even though C has no object-oriented hierarchies, this interface * defines the types GArc, GCompound, * GImage, GLabel, GLine, * GOval, GPolygon, GRect, * GRoundRect, and G3DRect as synonyms * for GObject. Doing so helps to clarify what types * are expected by each function and simplifies the process of * converting code from languages that implement full hierarchies. */ typedef struct GObjectCDT *GObject; #endif /* * Function: freeGObject * Usage: freeGObject(gobj); * ------------------------- * Frees the memory associated with the object. This operation is * not necessary for objects that have been installed in a window. * Adding a GObject to a GWindow or a * GCompound transfers ownership to the container, * which assumes responsibility for freeing the object. */ void freeGObject(GObject gobj); /* * Function: getX * Usage: x = getX(gobj); * ---------------------- * Returns the x-coordinate of the object. */ double getXGObject(GObject gobj); /* * Function: getY * Usage: y = getY(gobj); * ---------------------- * Returns the y-coordinate of the object. */ double getYGObject(GObject gobj); /* * Function: getLocation * Usage: pt = getLocation(gobj); * ------------------------------ * Returns the location of this object as a GPoint. */ GPoint getLocation(GObject gobj); /* * Function: setLocation * Usage: setLocation(gobj, x, y); * ------------------------------- * Sets the location of this object to the specified coordinates. */ void setLocation(GObject gobj, double x, double y); /* * Function: move * Usage: move(gobj, dx, dy); * -------------------------- * Moves the object on the screen using the displacements * dx and dy. */ void move(GObject gobj, double dx, double dy); /* * Function: getWidth * Usage: width = getWidth(gobj); * ------------------------------ * Returns the width of this object, which is defined to be the width of * the bounding box. */ double getWidthGObject(GObject gobj); /* * Function: getHeight * Usage: height = getHeight(gobj); * -------------------------------- * Returns the height of this object, which is defined to be the height * of the bounding box. */ double getHeightGObject(GObject gobj); /* * Function: getSize * Usage: size = getSize(gobj); * ---------------------------- * Returns the size of the object as a GDimension. */ GDimension getSize(GObject gobj); /* * Function: getBounds * Usage: rect = getBounds(gobj); * ------------------------------ * Returns the bounding box of this object, which is defined to be the * smallest rectangle that covers everything drawn by the figure. The * coordinates of this rectangle do not necessarily match the location * returned by getLocation. Given a GLabel * object, for example, getLocation returns the coordinates * of the point on the baseline at which the string begins; the * getBounds method, by contrast, returns a rectangle that * covers the entire window area occupied by the string. */ GRectangle getBounds(GObject gobj); /* * Function: setColor * Usage: setColor(gobj, color); * ----------------------------- * Sets the color used to display this object. The color * string is usually one of the predefined color names: * * BLACK
* BLUE
* CYAN
* DARK_GRAY
* GRAY
* GREEN
* LIGHT_GRAY
* MAGENTA
* ORANGE
* PINK
* RED
* WHITE
* YELLOW
* *

The case of the individual letters in the color name is ignored, as * are spaces and underscores, so that the color DARK_GRAY * can be written as "Dark Gray". */ void setColorGObject(GObject gobj, string color); /* * Function: getColor * Usage: color = getColor(gobj); * ------------------------------ * Returns the color used to display this object. This color is * always returned as a string in the form "#rrggbb", * where rr, gg, and bb are * the red, green, and blue components of the color, expressed as * two-digit hexadecimal values. */ string getColorGObject(GObject gobj); /* * Function: setVisible * Usage: setVisible(gobj, flag); * ------------------------------ * Sets whether this object is visible. */ void setVisibleGObject(GObject gobj, bool flag); /* * Function: isVisible * Usage: if (isVisible(gobj)) . . . * --------------------------------- * Returns true if this object is visible. */ bool isVisibleGObject(GObject gobj); /* * Function: sendForward * Usage: sendForward(gobj); * ------------------------- * Moves this object one step toward the front in the z dimension. * If it was already at the front of the stack, nothing happens. */ void sendForward(GObject gobj); /* * Function: sendToFront * Usage: sendToFront(gobj); * ------------------------- * Moves this object to the front of the display in the z dimension. * By moving it to the front, this object will appear to be on top of the * other graphical objects on the display and may hide any objects that * are further back. */ void sendToFront(GObject gobj); /* * Function: sendBackward * Usage: sendBackward(gobj); * -------------------------- * Moves this object one step toward the back in the z dimension. * If it was already at the back of the stack, nothing happens. */ void sendBackward(GObject gobj); /* * Function: sendToBack * Usage: sendToBack(gobj); * ------------------------ * Moves this object to the back of the display in the z dimension. * By moving it to the back, this object will appear to be behind the other * graphical objects on the display and may be obscured by other objects * in front. */ void sendToBack(GObject gobj); /* * Function: contains * Usage: if (contains(gobj, x, y)) . . . * -------------------------------------- * Returns true if the specified point is inside the object. */ bool containsGObject(GObject gobj, double x, double y); /* * Function: getType * Usage: type = getType(gobj); * ---------------------------- * Returns the subtype of the object as a string, as in "GOval" * or "GRect". */ string getType(GObject gobj); /* * Function: getParent * Usage: parent = getParent(gobj); * -------------------------------- * Returns a pointer to the GCompound that contains this * object. Every GWindow is initialized to contain a single * GCompound that is aligned with the window. Adding * objects to the window adds them to that GCompound, * which means that every object you add to the window has a parent. * Calling getParent on the top-level GCompound * returns NULL. */ GObject getParent(GObject gobj); /* Functions that apply to several types */ /* * Function: setSize * Usage: setSize(gobj, width, height); * ------------------------------------ * Changes the size of this object to the specified width and height. This * method applies to the types GOval, GImage, * and GRect (and its subclasses). */ void setSize(GObject gobj, double width, double height); /* * Function: setBounds * Usage: setBounds(gobj, x, y, width, height); * -------------------------------------------- * Changes the bounds of this object to the specified values. This * method applies to the types GOval, GImage, * and GRect (and its subclasses). */ void setBounds(GObject gobj, double x, double y, double width, double height); /* * Function: setFilled * Usage: setFilled(gobj, flag); * ----------------------------- * Sets the fill status for gobj, where false * is outlined and true is filled. */ void setFilled(GObject gobj, bool flag); /* * Function: isFilled * Usage: if (isFilled(gobj)) . . . * -------------------------------- * Returns true if gobj is filled. */ bool isFilled(GObject gobj); /* * Function: setFillColor * Usage: setFillColor(gobj, color); * --------------------------------- * Sets the color used to display the filled region of this rectangle. */ void setFillColor(GObject gobj, string color); /* * Function: getFillColor * Usage: color = getFillColor(gobj); * ---------------------------------- * Returns the color used to display the filled region of gobj. * rectangle. If none has been set, getFillColor returns * the empty string. */ string getFillColor(GObject gobj); /* * Type: GRect * ----------- * This type represents a graphical object whose appearance consists of a * rectangular box. For example, the following code adds a filled, red, * 200x100 rectangle * at the upper left corner of the graphics window: * *

 *    main() {
 *       GWindow gw = newGWindow(500, 300);
 *       printf("This program draws a red rectangle at (0, 0).\n")
 *       GRect rect = newGRect(0, 0, 200, 100);
 *       setFilled(rect, true);
 *       setColor(rect, "RED");
 *       add(gw, rect);
 *    }
 *
*/ typedef GObject GRect; /* * Function: newGRect * Usage: rect = newGRect(x, y, width, height); * -------------------------------------------- * Creates a new GRect with the specified bounds. By * default, the rectangle is unfilled. */ GRect newGRect(double x, double y, double width, double height); /* * Type: GRoundRect * ---------------- * This type represents a rectangular box with rounded corners. */ typedef GRect GRoundRect; /* * Function: newGRoundRect * Usage: GRoundRect rect = newGRoundRect(x, y, width, height, corner); * -------------------------------------------------------------------- * Creates a new GRoundRect with the specified dimensions. * The corner parameter specifies the diameter of the arc * forming the corner. */ GRoundRect newGRoundRect(double x, double y, double width, double height, double corner); /* * Type: G3DRect * ------------- * This type represents a rectangular box that can appear raised or lowered. */ typedef GRect G3DRect; /* * Function: newG3DRect * Usage: G3DRect rect = newG3DRect(x, y, width, height, raised); * -------------------------------------------------------------- * Creates a new G3DRect with the specified dimensions. * The corner parameter specifies whether this rectangle * should appear raised. */ G3DRect newG3DRect(double x, double y, double width, double height, bool raised); /* * Function: setRaised * Usage: setRaised(rect, raised); * ------------------------------- * Indicates whether this object appears raised. */ void setRaised(G3DRect rect, bool raised); /* * Function: isRaised * Usage: if (isRaised(rect)) ... * ------------------------------ * Returns true if this object appears raised. */ bool isRaised(G3DRect rect); /* * Type: GOval * ----------- * This type represents an oval inscribed in a rectangular box. * For example, the following code displays a filled green oval * inscribed in the graphics window: * *
 *    main() {
 *       GWindow gw = newGWindow(500, 300);
 *       printf("This program draws a green oval filling the window.\n");
 *       GOval oval = newGOval(getWidth(gw), getHeight(gw));
 *       setFilled(oval, true);
 *       setColor(oval, "GREEN");
 *       add(gw, oval);
 *    }
 *
*/ typedef GObject GOval; /* * Function: newGOval * Usage: oval = newGOval(x, y, width, height); * -------------------------------------------- * Creates a new GOval with the specified bounds. By default, * the oval is unfilled. */ GObject newGOval(double x, double y, double width, double height); /* * Type: GLine * ----------- * This type represents a line segment. For example, the following code * adds lines that mark the diagonals of the graphics window: * *
 *    main() {
 *       GWindow gw = newGWindow(500, 300);
 *       printf("This program draws the diagonals on the window.\n");
 *       add(gw, newGLine(0, 0, getWidth(gw), getHeight(gw)));
 *       add(gw, newGLine(0, getHeight(gw), getWidth(gw), 0));
 *    }
 *
*/ typedef GObject GLine; /* * Function: newGLine * Usage: line = newGLine(x0, y0, x1, y1); * --------------------------------------- * Creates a new graphical line connecting the points * (x0y0) and * (x1y1). */ GObject newGLine(double x0, double y0, double x1, double y1); /* * Function: setStartPoint * Usage: setStartPoint(gline, x, y); * ---------------------------------- * Sets the start point for the line to (xy), * leaving the end point unchanged. This method is therefore different * from setLocation, which moves both components of the * line segment. */ void setStartPoint(GLine line, double x, double y); /* * Function: setEndPoint * Usage: setEndPoint(line, x, y); * ------------------------------- * Sets the end point for the line to (xy), * leaving the start point unchanged. */ void setEndPoint(GLine line, double x, double y); /* * Function: getStartPoint * Usage: pt = getStartPoint(gobj); * -------------------------------- * Returns the point at which a GLine or GArc starts. */ GPoint getStartPoint(GObject gobj); /* * Function: getEndPoint * Usage: pt = getEndPoint(gobj); * ------------------------------ * Returns the point at which a GLine or GArc ends. */ GPoint getEndPoint(GObject gobj); /* * Type: GArc * ---------- * This type represents an elliptical arc. The arc is specified by the * following parameters: * *

    *
  • The coordinates of the bounding rectangle (x, * y, width, height) *
  • The angle at which the arc starts (start) *
  • The number of degrees that the arc covers (sweep) *
* *

All angles in a GArc description are measured in * degrees moving counterclockwise from the +x axis. Negative * values for either start or sweep indicate * motion in a clockwise direction. * */ typedef GObject GArc; /* * Function: newGArc * Usage: arc = newGArc(x, y, width, height, start, sweep); * -------------------------------------------------------- * Creates a new GArc consisting of an elliptical arc. * */ GArc newGArc(double x, double y, double width, double height, double start, double sweep); /* * Function: setStartAngle * Usage: setStartAngle(arc, start); * --------------------------------- * Sets the starting angle for this GArc object. */ void setStartAngle(GArc arc, double start); /* * Function: getStartAngle * Usage: angle = getStartAngle(arc); * ---------------------------------- * Returns the starting angle for this GArc object. */ double getStartAngle(GArc arc); /* * Function: setSweepAngle * Usage: setSweepAngle(arc, start); * --------------------------------- * Sets the sweep angle for this GArc object. */ void setSweepAngle(GArc arc, double start); /* * Function: getSweepAngle * Usage: angle = getSweepAngle(arc); * ---------------------------------- * Returns the sweep angle for this GArc object. */ double getSweepAngle(GArc arc); /* * Function: setFrameRectangle * Usage: setFrameRectangle(arc, x, y, width, height); * --------------------------------------------------- * Changes the boundaries of the rectangle used to frame the arc. */ void setFrameRectangle(GArc garc, double x, double y, double width, double height); /* * Function: getFrameRectangle * Usage: rect = getFrameRectangle(arc); * ------------------------------------- * Returns the boundaries of the rectangle used to frame the arc. */ GRectangle getFrameRectangle(GArc arc); /* * Type: GLabel * ------------ * This subtype represents a text string. For example, the following code * adds a GLabel containing "hello, world" to * the center of the window: * *

 *    main() {
 *       GWindow gw;
 *       GLabel label;
 *       double x, y;
 *
 *       printf("This program draws the 'hello, world' message.\n");
 *       gw = newGWindow(600, 400);
 *       label = newGLabel("hello, world");
 *       setFont(label, "SansSerif-18");
 *       x = (getWidth(gw) - getWidth(label)) / 2;
 *       y = (getHeight(gw) + getFontAscent(label)) / 2;
 *       setLocation(label, x, y);
 *       add(gw, label);
 *    }
 *
* * Controlling the appearance and positioning of a GLabel * depends on understanding the following terms: * *

    *
  • The baseline is the horizontal line on which the * characters rest. *
  • The origin is the point on the baseline at which * the label begins. *
  • The height is the distance that separate two * successive lines. *
  • The ascent is the maximum distance a character * in this font extends above the baseline. *
  • The descent is the maximum distance a character * in this font extends below the baseline. *
* */ typedef GObject GLabel; /* * Function: newGLabel * Usage: label = newGLabel(str); * ------------------------------ * Creates a GLabel object containing the specified string, * positioned with an origin of (0, 0). */ GLabel newGLabel(string str); /* * Function: setFont * Usage: setFont(label, font); * ---------------------------- * Changes the font used to display the GLabel as specified by * the string font, which has the following format: * *
 *    family-style-size
 *
* * where both style and size are optional. * If any of these elements are missing or specified as an asterisk, * the existing value is retained. */ void setFont(GLabel label, string font); /* * Function: getFont * Usage: font = getFont(label); * ----------------------------- * Returns the current font for the GLabel. */ string getFont(GLabel label); /* * Function: setLabel * Usage: setLabel(label, str); * ---------------------------- * Changes the string stored within the GLabel object, so that * a new text string appears on the display. */ void setLabel(GLabel label, string str); /* * Function: getLabel * Usage: str = getLabel(label); * ----------------------------- * Returns the string displayed by this object. */ string getLabel(GLabel label); /* * Function: getFontAscent * Usage: ascent = getFontAscent(label); * ------------------------------------- * Returns the maximum distance strings in this font extend above * the baseline. */ double getFontAscent(GLabel label); /* * Function: getFontDescent * Usage: descent = getFontDescent(label); * --------------------------------------- * Returns the maximum distance strings in this font descend below * the baseline. */ double getFontDescent(GLabel label); /* * Type: GImage * ------------ * This subtype represents an image from a file. For example, the * following code adds a GImage containing the Stanford * tree at the center of the window, assuming that the image file * StanfordTree.png exists, either in the current * directory or an images subdirectory: * *
 *    main() {
 *       printf("This program draws the Stanford tree.\n");
 *       GWindow gw = newGWindow(600, 400);
 *       GImage tree = newGImage("StanfordTree.png");
 *       double x = (getWidth(gw) - getWidth(tree)) / 2;
 *       double y = (getHeight(gw) - getHeight(tree)) / 2;
 *       add(gw, tree, x, y);
 *    }
 *
*/ typedef GObject GImage; /* * Function: newGImage * Usage: GImage image = newGImage(filename); * ------------------------------------------ * Constructs a new image by loading the image from the specified * file, which is either in the current directory or a subdirectory named * images. The upper left corner of the image is positioned * at the origin. */ GImage newGImage(string filename); /* * Type: GPolygon * -------------- * This subtype represents a polygon bounded by line segments. * The newGPolygon function creates an empty polygon. * To complete the figure, you need to add vertices to the polygon * using the functions * addVertex, * addEdge, * and addPolarEdge. * As an example, the following code adds a filled red octagon to * the center of the window: * *
 *    main() {
 *       GWindow gw;
 *       GPolygon stopSign;
 *       double edge;
 *       int i;
 *
 *       printf("This program draws a red octagon.\n");
 *       gw = newGWindow(600, 400);
 *       edge = 75;
 *       stopSign = newGPolygon();
 *       addVertex(stopSign, -edge / 2, edge / 2 + edge / sqrt(2.0));
 *       for (i = 0; i < 8; i++) {
 *          addPolarEdge(stopSign, edge, 45 * i);
 *       }
 *       setFilled(stopSign, true);
 *       setColor(stopSign, "RED");
 *       add(gw, stopSign, getWidth(gw) / 2, getHeight(gw) / 2);
 *    }
 *
* */ typedef GObject GPolygon; /* * Function: newGPolygon * Usage: poly = newGPolygon(); * ---------------------------- * Constructs a new empty polygon. */ GPolygon newGPolygon(void); /* * Function: addVertex * Usage: addVertex(poly, x, y); * ----------------------------- * Adds a vertex at (x, y) relative to the polygon * origin. */ void addVertex(GPolygon poly, double x, double y); /* * Function: addEdge * Usage: addEdge(poly, dx, dy); * ----------------------------- * Adds an edge to the polygon whose components are given by the displacements * dx and dy from the last vertex. */ void addEdge(GPolygon poly, double dx, double dy); /* * Function: addPolarEdge * Usage: addPolarEdge(poly, r, theta); * ------------------------------------ * Adds an edge to the polygon specified in polar coordinates. The length * of the edge is given by r, and the edge extends in * direction theta, measured in degrees counterclockwise * from the +x axis. */ void addPolarEdge(GPolygon poly, double r, double theta); /* * Function: getVertices * Usage: vec = getVertices(poly); * ------------------------------- * Returns a vector whose elements are pointers to the GPoint values that * represent the vertices. This vector is shared with the internal data * structure of the GPolygon and must not be freed by the client. */ Vector getVertices(GPolygon poly); /* * Type: GCompound * --------------- * This subtype consists of a collection of other graphical objects. * Once assembled, the internal objects can be manipulated as a unit. * The GCompound keeps track of its own position, and all * items within it are drawn relative to that location. */ typedef GObject GCompound; /* * Function: newGCompound * Usage: comp = newGCompound(); * ----------------------------- * Creates a new graphical compound with no internal components. */ GObject newGCompound(void); /* * Function: add * Usage: add(compound, gobj); * --------------------------- * Adds the object to the compound. */ void addGCompound(GCompound compound, GObject gobj); /* * Function: add * Usage: add(compound, gobj); * --------------------------- * Removes the object from the compound. */ void removeGCompound(GCompound compound, GObject gobj); /* * Friend function: getGObjectCompound * Usage: gobj = getGObjectCompound(GCompound compound, double x, double y); * ------------------------------------------------------------------------- * Returns the topmost object covering x and y, or NULL if * no such object exists. */ GObject getGObjectCompound(GCompound compound, double x, double y); /* * Friend type: ObjectTypeBits * --------------------------- * This enumeration identifies a GObject type in a way that simplifies * checking whether a particular function is legal on that object. */ typedef enum { GARC = 1<<0, GCOMPOUND = 1<<1, GIMAGE = 1<<2, GLABEL = 1<<3, GLINE = 1<<4, GOVAL = 1<<5, GPOLYGON = 1<<6, GRECT = 1<<7, G3DRECT = 1<<8, GROUNDRECT = 1<<9, GINTERACTOR = 0x1F<<10, GBUTTON = 1<<10, GCHECKBOX = 1<<11, GCHOOSER = 1<<12, GSLIDER = 1<<13, GTEXTFIELD = 1<<14 } GObjectTypeBits; #endif