GUIManipulator-class

Derived from: public Manipulator

Declared in: GUIManipulator.h


Overview

The GUIManipulator-class inherits from the class Manipulator. This class is an intermediate class that declares methods that are common to StatusBarGUIManipulator and WindowGUIManipulator classes. You should never make a manipulator class that is based directly on GUIManipulator-class. Instead use the StatusBarGUIManipulator and WindowGUIManipulator classes as the base for your manipulators.

Class GUIManipulator defines an API that is to be used by manipulators that create some kind of GUI where the user can adjust the manipulating. This GUI can be limited to allowing the user click on the image with mouse, or it can be a separate window containing multiple gizmos and gadgets. GUIManipulator API allows for quite powerful add-ons, even the tools could be made add-ons (although there would be some complications). In future the API for GUI-manipulators will be changed a little, but the changes should not be too dramatic.


Constructor and Destructor

GUIManipulator()

  GUIManipulator()
Does nothing.

~GUIManipulator()

  virtual ~GUIManipulator()
Does nothing.

Member Functions

ChangeSettings()

  virtual  void*  ChangeSettings(ManipulatorSettings* 
    settings)
This function can be re-implemented in derived classes to change the settings for the manipulator. If your manipulator has settings it should store them in an instance of a class that is based on ManipulatorSettings class. This way the settings of one instance of manipulator can be stored and then later given to another instance of that same manipulator-class. You can also use this method to change the settings for the manipulator whenever the user adjust the settings with the GUI. A basic version of this method would do the following:
  MyOwnManipulatorSettings *s;
  s = cast_as(settings,MyOwnManipulatorSettings);
  if (s != NULL)
    the_current_settings = *s;
Currently this function is not called from anywhere outside the manipulator's code, but this may change in the future. The default version of this function does nothing.

Draw()

  virtual  BRegion  Draw(BView* target_view,
    float magnify_scale)
This function can be implemented in derived classes to draw some kind of GUI on top of the image. The parameter target_view is the view where the drawing should be done. Because the zoom-level of the image might be something else than 1 the magnify_scale is provided. You can convert from the bitmap's coordinates to view's coordinates by multiplying the bitmap's coordinates with magnify_scale. The function should return the smallest possible region that contains the areas that this function drew to. The returned region should be in the view's coordinate space.

The following code snippet demonstrates how this function should work. Here we stroke a rectangle that surrounds bitmaps pixels (2,2) , (3,2) , (2,3) and (3,3).

  BRect rect;
  rect.left = floor(2*mag_scale);
  rect..right = ceil((3+1)*mag_scale-1);
  rect.top = floor(2*mag_scale);
  rect.bottom = ceil((3+1)*mag_scale-1);

  target_view->StrokeRect(rect);
  
  BRegion region;
  region.Set(rect);
  rect.InsetBy(1,1);
  region.Exclude(rect);
  return region;
In ArtPaint at least cropping and rotation make use of this function.

ManipulateBitmap()

  virtual  BBitmap*  ManipulateBitmap(ManipulatorSettings* 
    settings, BBitmap* original, Selection* selection, 
    BStatusBar* status_bar)
This is implemented by derived classes to manipulate the given bitmap. It works in the same way as the version of this function that was declared in Manipulator-class. The additional parameter settings determines the parameters which should be used to do the manipulation.

There are a few special cases that need to be acounted for when implementing this function. The first case is that if the settings indicate that no manipulation should be done the function should return NULL.

The second special case comes from the fact that manipulator might have changed the contents of some bitmap in PreviewBitmap-function. If the original is a pointer to the same bitmap that was last set as a preview bitmap through SetPreviewBitmap-function (or in the constructor), we should use a copy of the preview bitmap as the original instead of the original. The following piece of code demonstrates how to select the appropriate target and source for the manipulation.

  BBitmap *target;
  BBitmap *source;
  if (original == preview_bitmap) {
    source = copy_of_the_preview_bitmap;
    target = original;
  }
  else {
    source = original;
    target = new BBitmap(original->Bounds(),B_RGB32,FALSE);
  }

  // Do the manipulation from source to target

  return target;
For more information about the preview-bitmap and its copy see the SetPreviewBitmap()-function.

ManipulatorCursor()

  virtual const void* ManipulatorCursor()
This function should return a pointer to data that can be used to set a cursor through BApplication's SetCursor-function. The proper structure of such data is documented in the BeBook. The cursor will be changed to this whenever the add-on is in use and the cursor is on the image. An example of this function's work can be seen in rotation and translation. The default version of this function returns NULL, which indicates that the cursor is shown in its default form.

MouseDown()

  virtual void MouseDown(BPoint point, 
    uint32 buttons, BView* target_view,
    bool first_click)
This function can be implemented in derived classes to respond to mouse-events. This function should record the necessary information about the mouse-click (i.e. the point and perhaps buttons and should return as quickly as possible. This function should not poll the mouse like a normal MouseDown-function of BView is supposed to do. Instead this function will be called repeatedly while the mouse-button is held down.

The parameter point is in the bitmap's coordinate space and indicates the location of the cursor in the image. The parameter buttons indicates what mouse-buttons are held down. The parameter target_view can be used to get more information (e.g. what modifiers are held down). The window where target_view resides is already locked when this function is called. The parameter first_click indicates whether or not this is the first time this function is called after the mouse-button was pressed down.

The default version of this function does nothing.


PreviewBitmap()

  virtual int32 PreviewBitmap(Selection* selection,
    bool full_quality = FALSE, BRegion* updated_region
    = NULL)
This function can be used to calculate a preview of the manipulator's effect. The preview should be calculated to the preview-bitmap that has been set through SetPreviewBitmap()-function. The execution of this function should be relatively fast. This allows the real-time preview of the effect when the user modifies its parameters.

The main technique for making a preview faster is making it at a lower resolution. For example if only every other pixel from every other row is calculated, the calculation will be four times as fast as calculating with full resolution. The used resolution should be decided in the SetPreviewBitmap()-function.

If the parameters for the effect have not changed after the last time this function was called, the resolution should be increased. This allows the user to stop changing parameters and see a more accurate preview of the effect. When the parameters change we should again return to the lower resolution. If the full_quality is true, then the effect should be calculated at the highest possible resolution. When calculating the image at a low resolution, it is only required to set the calculated points in the preview-bitmap. The calculated points will be automatically copied to their neighbours to cover the whole image before displaying it.

The updated_region is a pointer to a region which should be set to indicate the area that the preview affects. The selection determines what part of the image should be affected by the preview.

This function should return the resolution that was used in calculating the preview. For example if every other pixel on every other row was calculated, the returned value should be 2. If the manipulator does not do preview, but draws a GUI, the returned value should be DRAW_ONLY_GUI. If the manipulator does not do preview and does not draw a GUI the returned value should be DRAW_NOTHING.


Reset()

  virtual void Reset(Selection* selection)
This function should put the bitmap that has been used in previewing to the state that it was before any previewing. If the selection has been changed while previewing, it should also be returned to the state where it was before previewing started. Note that normal manipulators should not change the selection in any way.

ReadSettings() see WriteSettings()


ReturnHelpString()

  virtual char* ReturnHelpString()
This function should return a string that gives the user some information on what to do with the manipulator. The string will be displayed at the bottom of the status-bar in the paint-window.

ReturnSettings()

  virtual ManipulatorSettings* ReturnSettings()
This function should be implemented to return a pointer to an instance of class that is subclass of ManipulatorSettings. The object that the returned pointer points to will become the property of the calling function.

SetPreviewBitmap()

  virtual void SetPreviewBitmap(BBitmap* bitmap)
This function should be implemented to take note whenever the previewed bitmap changes. The bitmap will become the bitmap that the preview will be done to. Generally also a copy of the bitmap is required to allow the proper calculation of the effect and to allow Reset() to work.

This function should also decide what kind of preview resolution can be used. It should decide the lower and upper limits for the resolution. The decision should be based on the size of the bitmap and the speed of the machines CPU. If the PreviewBitmap()-function uses multiple threads (as it usually should) you should take the number of CPUs into account when calculating the resolution. The resolutions should be something between 16x16 pixel blocks and 1x1 pixel blocks. The 16x16 pixel resolution will look quite bad unless the image is excessively big, so it should be avoided. Also the cost of padding will be effectively same with all resolutions, so lowering the resolution too much does not really help. It is always a better idea to optimize your preview calculating code and perhaps simplify some of the algorithms to obtain speed than it is to lower resolution.


WriteSettings(), ReadSettings()

  virtual status_t WriteSettings(BNode* node)

  virtual status_t ReadSettings(BNode* node)
These functions can be used to write and read the manipulators settings from the node. The node will be the file that the manipulator's add-on was loaded from. These functions should write and read the settings from the node's attributes. The functions can give the node any attributes they wish and it is completely upon the manipulator to decide what kind of information is stored in the attributes. The returned value should indicate success by returning B_NO_ERROR. If unsuccesfull, they should return a descriptive error-code.

The default versions of these functions do nothing.