Image Editor • Architecture
There are two main parts of Image Editor Suite - image editor visual component which contains and displays edited image and drawer that is connected to image editor. As visual component, image editor receives all mouse and keyboard events, translates them into special events, like start/end drawing, etc., and calls appropriated methods of connected drawer. Drawer uses passed link to image editor to receive all the needed information about drawing canvas, current colors, mouse positions, etc., and draws the graphics.
||User of application created with Image Editor Suite components
||TImageEditor component parts
||Non-visual drawers (TCustomDrawer component descendants)
||Relations (see text below)
As you can see, USER during seeing (2) and editing images produces mouse and key events (8), which are processed by Messages part, translated to Display for zooming and scrolling (3) and converted to Drawers' method calls (11). Drawers is a collection of drawer objects (TCustomDrawer descendants) and each of them has simple set of methods (StartDraw, Draw, StopDraw, etc.) which are used for editing the image. Each drawer operates with Context (12), that includes ForeColor, BackColor, Tool, Mode, Option and Value property, which can be changed by USER (10), Canvas, distrubuted by Image (7) and special context properties DrawerData and DrawerObject which are used by drawers for storing any drawing data (13). When canvas of Image is changed (6), the Image invalidates Display to show all the changes (1). Also USER are notified about some important changes by special events (9). Of course, the edited image can be obtained (4) for any external processing and can be put back to the editor (5).
- Image change notification for invalidating control.
- Displaying zoomed and scrolled image.
- Scrolling and zooming.
- Getting the edited image by GetImage method for external processing.
- Setting the edited image from external bitmap object.
- Changing the edited image by canvas, distributed to Context
- Disributing the edit canvas to Context
- Messages produced by USER
- Special notification messages about image changing
- Changing the Context's data (Tool, Mode, Option, Value properties) by USER
- Calling the Drawers' methods from message handlers
- Context data (Canvas, ForeColor, BackColor, Tool, Mode, Option, Value, DrawerData, DrawerObject properties) distributed from image editor to drawer components
- Changing distributed Canvas and setting DrawerData and DrawerObject properties
This is just internal architecture and you can forget about it right now, because there is only thing that you need to know when working with Image Editor Suite: any functionality is realized in drawer objects, connected to main image editor component. Just use ready-to-use TStandardDrawer, TPluginDrawer, which allows to use drawers in external DLLs, TSimpleDrawer, that can realize any drawing functionality with large set of events, of just create your own drawer components.
Any image editor in the application can be connected with any count of drawers by collection-type Drawers property, and each drawer can be used in any count of image editors.
Link to current image editor instance is passed into any drawer's function and all drawing context (current tool, tool settings, etc.) is saved in the image editor and drawer stores nothing, so all the drawer needs to know the drawing context is to explore appropriate properties of the passed image editor.
Each drawer method returns boolean value to notify image editor whether this call was processed or not. If returned value is False, method of the next drawer in collection are called, otherwise image editor stops drawer enumerating. The drawers in imaged editor are enumerated in Drawers collection order, so you can "override" the functionality of any drawer by creating your own drawer processed the same context (Tool, Mode, etc.) and placing this drawer before drawer you want to override.
There is another pleasant bonus in the architecture - whereas drawer does not store any global data, it can be realized in external plug-in DLL if you need it and can be connected at runtime using special drawer component with two lines of code.