Specifying Widget Flags

Gamma/Photon: Using Gamma™ with the Photon microGUIŽ, Version 4.0
Prev | Chapter 2. Classes | Next

# 2.2. Specifying Widget Flags

The syntax for handling widget flags in Gamma is somewhat unique. What follows is a brief description of how to set, test, and clear flags on widgets in two different ways. The first is through a non-standard use of the assignment operator, and the second is through method calls. Following these is a short discussion on using bitmasks for flags that are not independent. For more examples, see the tutorial Set, Test, and Clear Widget Flags in the Building Applications - a Tutorial chapter.

### 2.2.1. Setting Flags

Flags can be set for widget instance variables using the `=` (assignment) operator and the name of the flag.

| The `=` operator is used in a unique way in Gamma for setting widget flags. It does NOT assign a completely new value to the variable. Rather, it adds or removes the value of a flag in the variable. The `=` operator in this context of Gamma has the same effect as the `|=` operator in C.

For example, to highlight a pane called `Pane1`, you would set the `Pt_HIGHLIGHTED` flag in the `Pane1.flags` variable, as follows.

        Gamma> Pane1.flags = Pt_HIGHLIGHTED;
        256

You can set several flags at once as long as you separate them by the `|` (bitwise or) operator. For example, to set `Pane1` and etch its highlight, you would do this:

        Gamma> Pane1.flags = Pt_SET | Pt_ETCH_HIGHLIGHT;
        514

You can also set flags on a widget by assigning the value of the `flags` variable from another widget. When doing this, it is possible to mask one or more of the flags, so that they aren't set on the second widget. This requires conjoining the variable with negated constant(s) using the & (bitwise and) and ~ (bitwise not) operators. For example, to copy the flags from the example above to another pane called `Pane2` without the `Pt_ETCH_HIGHLIGHT` flag or the `Pt_SET` flags on, you could do the following:

        Gamma> Pane2.flags = Pane1.flags & ~Pt_ETCH_HIGHLIGHT & ~Pt_SET;
        256

### 2.2.2. Testing Flags

If you need to check a variable to see if a constant flag is set on it or not, you can test it. Testing is done with the `&` (bitwise and) operator, the same as in C. However, once the `flags` variable has been conjoined with the constant, that value must be checked to see if it is equal to `0`. This is because in Gamma `0` does not have the logical value of false. You have to make an explicit logical test.

For example, to test `Pane1` and `Pane2` for `Pt_ETCH_HIGHLIGHT`, you could do this:

        Gamma> (Pane1.flags & Pt_ETCH_HIGHLIGHT) != 0;
        t
        Gamma> (Pane2.flags & Pt_ETCH_HIGHLIGHT) != 0;
        nil

Gamma returns t if the flag variable is set, or nil if it is not set.

### 2.2.3. Clearing Flags

Flags are cleared using the `cons` function and `nil`. You make a cons cell with the flag as its first element and `nil` as its second element. This has the effect of giving the flag a value of `0`, like using the `&=` and `~` operators together in C. For example, to clear the `Pt_ETCH_HIGHLIGHT` and `Pt_HIGHLIGHTED` flags from `Pane1`, you would do this:

    Gamma> Pane1.flags = cons(Pt_ETCH_HIGHLIGHT, nil);
    (512)
    Gamma> Pane1.flags = cons(Pt_HIGHLIGHTED, nil);
    (256)
    Gamma> (Pane1.flags & (Pt_ETCH_HIGHLIGHT | Pt_HIGHLIGHT)) != 0;
    nil

Incidentally, the `cons` function can also be used to set flags. Just cons the flag to t instead of nil. For example, to set the `Pt_SET` flag on `Pane2`, you could do this:

    Gamma> Pane2.flags = cons(Pt_SET,t);
    (2 . t)
    Gamma> (Pane2.flags & Pt_SET) != 0;
    t

### 2.2.4. Using Widget Method Calls

As an alternative to using the assignment operator, you can set, test, and clear instance variable flags on widgets using the `SetBit`, `TestBit`, and `ClearBit` methods of `PtWidget`, which is the parent widget for all of the Widget Classes. (See PtWidget for more information.) These methods are in the `PhotonWidgets.lsp` library, so you must make a call to `require_lisp("PhotonWidgets.lsp")` before using them.

Continuing with the example of `Pane1` from above, you could set, test, and clear its `Pt_HIGHLIGHTED` flag as follows:

        Gamma> require_lisp("PhotonWidgets.lsp");
        "<pathname>PhotonWidgets.lsp"
        Gamma> Pane1.SetBit(#flags, Pt_HIGHLIGHTED);
        256
        Gamma> Pane1.TestBit(#flags, Pt_HIGHLIGHTED);
        t
        Gamma> Pane1.ClearBit(#flags, Pt_HIGHLIGHTED);
        (256)
        Gamma> Pane1.TestBit(#flags, Pt_HIGHLIGHTED);
        nil

Using these methods and/or the assignment operator as explained here, you should have no problem setting flags on most widgets.

### 2.2.5. Using Bitmasks and `cons`

Some flags are exclusive, meaning there can be only one of a group of them set at any given time. Setting one of these flags requires that any others in the group be unset first, but without unsetting those flags on the variable that are not part of the group. The easy way to do this is to use bitmasks and the `cons` function.

A bitmask consists of all the exclusive flags in the group ORed together. To set a flag, you simply `cons` it to the bitmask. For example, the `RtTrend` widget has a variable named `rttrend_flags`, with three flags that must be set exclusively: `Rt_GRID_IS_TRANSLUCENT`, `Rt_GRID_ABOVE_TRENDS`, and `Rt_TRENDS_ABOVE_GRID`. To set, for example, `Rt_GRID_ABOVE_TRENDS`, you would do this:

        Gamma>  mask = Rt_GRID_IS_TRANSLUCENT
                   | Rt_GRID_ABOVE_TRENDS
                   | Rt_TRENDS_ABOVE_GRID;
        1792
        Gamma> trend.rttrend_flags = cons(Rt_GRID_ABOVE_TRENDS, mask);
        (256 . 1792)
        Gamma> (trend.rttrend_flags & Rt_GRID_ABOVE_TRENDS) != 0;
        t

Doing this:

`cons(flags, mask)`

is exactly equivalent to doing this:

`(`original` & ~mask) | flags`

where `original` is the original value of the variable. To illustrate what happens at bitwise level, let's look at two flags on an imaginary variable:

        Flag 1       0010000
        Flag 2       0001000
        Bitmask      0011000

Suppose Flags `1` and `2` must be set exclusively from each other. In the example below, the variable has a few flags set already, including Flag `1`. We want set Flag `1` OFF and Flag `2` ON. Using the Bitmask, we AND the original flags of the variable to the inverse of the bitmask, turning both flags OFF. Then we OR the result to Flag `2` to turn Flag `2` ON.

        original:       10100010   Flag 1 and other flags are ON, Flag 2 is OFF.
        AND ~Bitmask    11001111
                        --------
        results:        10000010   Flag 1 is now OFF.

                        10000010   The other flags are still ON.
        OR Flag 2       00010000
                        --------
        final result:   10010010   Flag 2 is now ON as well.

### 2.2.6. Using `cons`: a Summary

The `cons` can be used in Gamma in different ways for different purposes. The following table gives a summary of how `cons` is used for handling widget flags.

Table 2-1. Using `cons` with widget flags.

Gamma Syntax | Meaning
--- | ---
widget.variable = flags; | widget.variable = (original | flags)
widget.variable = cons(flags, t); | widget.variable = (original | flags)
widget.variable = cons(flags, nil); | widget.variable = (original & ~flags)
widget.variable = cons(flags, mask); | widget.variable = (original & ~mask) | flags

Prev | Home | Next
Classes | Up | Specifying Colors

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.