Extension to the Interface Kit: GridView


Extension to the BeOS PR Interface Kit: GridView

Derived from: public BView

Declared in: GridView.h

Makes use of: Array2d.h

Author: Paolo Gatti

This class is not in the public domain - read usage conditions below.


Overview

A GridView is a BView which can be dynamically split by the end user into several smaller rectangular children. Child views don't need to have the same size as each other, and they are automatically resized, added or removed when the user drags their border.

This class also provides a way for the user to dynamically choose what will be displayed in each child view, either by clicking on the child or by dragging and dropping. The GridView is therefore an interesting choice as a container class for complex monitoring panels - the user, not the programmer, gets to choose which elements go where. With respect to a BShelf, GridViews are more rigid (you don't always manage to put a child exactly where you want it) but, at the same time, easier to reshape dynamically (a single mouse drag can affect several children at the same time).

The present documentation is currently unfinished, due to lack of time. If anyone wants to improve and clarify it, please contact me, I'll give you any details you might need and I'll include your work in the next release.


Usage

Some day I'll write this section down. Meanwhile, have fun experimenting with the enclosed example program. Click on the rectangles' borders and drag them around, changes are performed when you release the mouse button. The left and right buttons have different effects: the left button tries to move the shortest possible segment, while the right button tries to move the longest.


Hook Functions

ChildDetached() Called when the user makes a child view totally disappear. You might want to delete the detached child here.
ClickOnChild() Can be implemented to take some action - for instance open a pop-up menu - when the user clicks on an empty rectangle.
DrawEmptyChild() Can be implemented to draw the inside of a GridView rectangle which doesn't currently contain a child BView.
NewChild() Called when the user creates a new rectangle in a GridView.


Constructor and Destructor


GridView()

      GridView(BRect frame, const char *name, uint32 resizingMode = B_FOLLOW_NONE, uint32 flags = NULL, float bordersize = 2, float minseparation = 0)
      GridView(BMessage *archive)

Sets up a GridView with the frame rectangle, which is specified in the coordinate system of its eventual parent, and assigns the GridView an identifying name, which can be NULL.

resizingMode and flags are explained in the Be Book, in the BView chapter. In the current implementation of GridView, resizing is not supported. Use the default resizingMode value, B_FOLLOW_NONE, or expect some serious trouble. Making your window not resizable nor zoomable is a good idea, too.

bordersize is related to the width of the draggable border between two child views. Large values of bordersize lead to huge borders.

minseparation is the minimum distance, in pixels, that can be allowed between two consecutive separators. The default value, zero, is automatically replaced with a distance proportional to the border width.


~BView()

      virtual ~GridView(void)

Frees all memory the GridView allocated, and ensures that each of the GridView's descendants in the view hierarchy are also destroyed.

It's an error to delete a GridView while it remains attached to a window. Remove it from the window's view hierarchy before deleting it.


Static Functions


Instantiate()

      static GridView *Instantiate(BMessage *archive)

Returns a new GridView object, allocated by new and created with the version of the constructor that takes a BMessage archive. However, if the message does not contain archived data for a GridView, Instantiate() returns NULL.

See also: Archive()


Member Functions


AddChild(), RemoveChild()

      void AddChild(BView *aView, int32 id);
      void AddChild(BView *aView, int32 x, int32 y);
      bool RemoveChild(BView *aView);
      bool RemoveChild(int32 id);
      bool RemoveChild(int32 x, int32 y);

AddChild() makes aView a child of the GridView, provided that aView doesn't already have a parent. The new child is added to the GridView's list of children in the grid position specified by the x and y coordinates, or in the grid rectangle specified by id - an identifier returned by Id().

Since the user can dynamically resize the child views, you shouldn't add to a GridView views that cannot dynamically adapt to a new size.

A child can only be added to an already existing rectangle of the grid; this is why the default BView::AddChild() was removed from this class.

RemoveChild() removes a child view from the grid. The view to remove can be specified by direct reference, by its coordinates or its Id().


Archive()

      virtual status_t Archive(BMessage *archive, bool deep = true) const

Calls the inherited version of Archive(), then adds the current GridView's geometry to the BMessage archive.

See also: Instantiate()


ChildAt()

      BView *ChildAt(int32 id) const;
      BView *ChildAt(int32 x, int32 y) const;

Returns a pointer to the child which has been placed at the x, y coordinates, or in the rectangle with the given Id(). If the coordinates are out of range, or if no view has been attached to the specified rectangle, the return value is NULL.

Note that the BView version of ChildAt() has been hidden.


ChildDetached()

      virtual void ChildDetached(BView *view);

ChildDetached() is called by the GridView when the user, by resizing a child view to zero, effectively detached it from its view hierarchy. When ChildDetached() is called, the view is already detached from its parent, and can be safely deleted or added to another view.

The default version of ChildDetached() does nothing.

See also: NewChild()


ClickOnChild()

      virtual void ClickOnChild(BPoint point, int32 x, int32 y);

This function is called when the user clicks on a rectangle of the GridView, if there is no view attached to that rectangle or if that view does not implement MouseDown(). The rectangle is identified both via its coordinates x and y, and via the exact point the user clicked, expressed in the GridView coordinate system.

When called, this function should take some action to fill the currently empty rectangle - either add a predetermined view, or open a pop-up menu.

The default version of ClickOnChild() does nothing.


CountSeparators()

      int32 CountSeparators(int32 dir) const;

Returns how many separators, including the view's edges, currently split the GridView into vertical (dir == 0) or horizontal (dir = 1) slices.


DragSeparator()

      void DragSeparator(int32 idx[2], float coords[2], uint32 buttons);
      void DragSeparator(int32 x, int32 y, float cx, float cy, uint32 buttons);

DragSeparator() emulates a mouse dragging of a separator. It has the same effects as the user moving the mouse on the separator defined by idx[] (or by x and y), pushing the specified buttons and releasing them after dragging to the coordinates coords[] (or cx and cy).

The exact meaning of idx[] requires a longer explanation I will write some other day - a quick look at the code should be of some help. As an alternative you can uncomment some printf() in the source, recompile and launch the demo from a Terminal.


DrawEmptyChild()

      virtual void DrawEmptyChild(BRect rect, BRect updateRect);

This function can be implemented to draw something different than solid grey inside the rectangles which haven't been filled with a child view yet. rect defines the entire rectangle, updateRect is the part of the rectangle that needs redrawing.


Id()

      int32 Id(int32 x, int32 y) const;
      int32 Id(BPoint where) const;

Separators within a GridView don't usually extend from one side of the view to the opposite side. This means that a single child view, bounded by separators, can cover more than one pair of (x, y) coordinates.

Id() converts the (x, y) pair, or a where BPoint, to an identifier which is unique for each child view, and which can be used to identify the child.

Since the user can delete a view without warning, the result of Id() loses its meaning whenever the window thread is unlocked.


Lock(), Unlock()

      void Lock(void);
      void Unlock(void);

A Lock()ed GridView cannot be reshaped by the user. It behaves like a normal BView, until it gets Unlock()ed. Locking and unlocking can be safely nested, up to 2**32 - 1 times.


LockSep(), UnlockSep()

      void LockSep(void);
      void UnlockSep(void);

LockSep() locks the GridView's separators into place. The user will not be able to create new separators, only to move and resize the views so that their borders are aligned to an existing separator.

UnlockSep() reverses the effects of LockSep(). Locking and unlocking separators can be safely nested, up to 2**32 - 1 times.


NewChild()

      virtual void NewChild(int32 id);

This function can be implemented to take some action whenever a new rectangle is added to the GridView. A typical example could be adding a default view to fill the new rectangle:

       void NewChild(int32 id)
       {
           AddChild(new DefaultView(), id);
       }

See also: AddChild(), ChildDetached(), ClickOnChild()


SeparatorAt()

      float SeparatorAt(int32 dir, int32 n) const;

Returns the current position of the nth vertical (dir = 0) or horizontal (dir = 1) separator. The 0-th separator is always on the GridView's left (or top) border, the last one is on the right (or bottom) corner.

See also: CountSeparators()


RemoveChild(): see AddChild()


Unlock(): see Lock()


UnlockSep(): see LockSep()


Copying and Usage Conditions

GridView is distributed under the following conditions.

- You can redistribute the GridView sources freely, provided that the copyright notice and these conditions are included and remain unchanged.

- If you want to distribute a modified version of GridView, you should mail me about the changes you performed. You can add restrictions to the distribution of your changes, but the present conditions must be part of your distribution conditions.

- You can use the GridView code, or parts of it, within a freely distributable program, free of charge. Your only obligations are to email me about your program, and to state, in the program's "About" requester or in the documentation, that your program makes use of GridView, which is under Copyright © 1998 by Paolo Gatti.

- If you want to use GridView, or parts of it, in a shareware or commercial package, you must also send me a registered copy of your program, and of any later releases.

- This program is provided "as is", WITHOUT WARRANTY OF ANY KIND, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. Use at your own risk. The copyright holder CANNOT BE HELD RESPONSIBLE for any damage caused by the use of this program. Should the laws of a contry forbid this limitation of responsibility, either globally or only under certain conditions, then you cannot use the program in that country when those conditions apply.



Copyright © 1998 Paolo Gatti.

Be is a registered trademark; BeOS, BeBox, BeWare, GeekPort, the Be logo, and the BeOS logo are trademarks of Be, Inc.

Last modified November 1, 1998.