JumboDialog/JumboPalette component v1.0 for Borland Delphi developers guide.
Created by Pavel Vasev, july 2001.

JumboPalette developers guide

Description:

As I told in users guide section, JumboPalette (JP) is a creature used to choice, manage and edit palettes (gradations). Usually, it serves as a part of other programs.When some program requires user-defined palettes (example - visualisation kits), it can use JP to let user to choice them. In its own, JP is a complete separate component which interacts with user and performs palette-selection task. 

Programmer: Pavel Vasev 
Creation date: june 2001 
Component Name: JumboDialog/JumboPalette 
Version: 1.0 

If you have any questions or comments please email them to Pavel Vasev at contact@mail.ur.ru

 

Ok, I suppose that you saw users guide for JP. Now its time to speak about how to use it in your applications.
These topics are discussed here:

Distribution

For now, JD/JP is only available as a component for Delphi 5. Probably, it will work with earlier versions. I'm going to create C-compatible dll and VisualC++ versions. 
Please don't be confused of component name: "JumboDialog/JumboPalette". JumboPalette is a name of user-interface implementation, while JumboDialog is a name of Delphi component interface - together they form "JD/JP". 

I want to notify you, that this component is PostCard-Ware. If you enjoy it and you use it in your applications, please send a postcard of your town to: 

Pavel Vasev 
M.-Sibiryaka street, 56-17 
620151 Ecaterinburg 
Russia

 

JD/JP skeleton

I suppose that you already looked at "working with JumboPalette" topic in users guide. Lets color is defined by 32-bit integer in '0RGB' mode, where B is a lower byte. Then, palette is an array of so represented colors. All palettes in JD/JP have fixed size, defined before JD/JP is initialized. So, global palette size is a meaningful constant when working with JD/JP. Palette folder(PF) is an array of palettes. All palettes in all palette folders are same-sized. Each palette folder is stored in external bmp file, and all these *.bmp are stored in fixed directory. Each palette folder is stored in bmp as follows: 
1st scanline - represents 1st palette in PF
2nd scanline - represents 2nd palette in PF
... 
Nth scanline - represents Nth palette in PF
When JD/JP is initialized, it loads all bmp files found in specified directory. Bmp's height specifies the number of palettes in PF. If bmp's width does not match palette size, lines from bmp are resized. If bmp is not in 32depth format, lines from bmp are converted to 32bit color depth. 
When JD/JP is deinitialized, is saves all PF as bmp files to PF-directory in 32color-depth format. 

When you call JD/JP, it executes modal dialog which interacts with user and allows him to select a palette, manage or create palettes. If user choiced a palette to activate (e.g. pressed ok button), you will have an access to this palette.  

Totally, you can: 
1. Execute JP dialog 
Execution is described below in "Using JD/JP in ..." sections. For example, in Delphi it looks like this: 
if JumboDialog1.Execute then begin  
     p := JumboDialog1.DupResult( nil,Form1.Width,true );  
    ...  
    FreeMem( p );  
end;  
2. So, recieve selected palette 
for example by pointer, like this: "ptr := JumboDialog1.ResultPtr;" or as shown in '1' 
3. And recieve recently selected palettes  
you can also do it in extended way as in '4' 
4. Manipulate on palette folders as you want using JD/JP API, so '2' and '3' are subsets of '4'  
A variety of functions are provided to access PFs. You can use them in your code anytime you want, also when you program your own tools as in '5'. You can do anything you want, for example programmatically create PF and add calculated palettes. 
5. Add your own tools to JP so user can use them.  
I created just a simple set of tools to edit and manage palettes. You can extend this set; this is described in 'Using JD/JP in ...' topics.

 

Using JP in Delphi

This version of JD/JP component includes no separate installation program. Therefore you have to copy all the files from "\DelphiSource\" directory located in the supplied Zip-File at first in a directory of your will. 
You will have to add the JD/JP component, to the component library before you can use it; to do that, install "JumboDialog.pas". After installation, the "JumboDialog" button will appear at "Dialogs" page. 
 

Ok, now you are ready to look at topics below.

 
 

Simple developers interface

The technique is as follows. When you install JD/JP, you will recieve TJumboDialog class. Put it into your form class using design manager. Then, set the design-time properties as you need. The main are 
PalettePath - a path to palette folder's bmp files, usualy relative like "Palettes\" (default)
PaletteSize - a palette size you want to use. JD/JP assume this palsize in all palette operations. So you will work with palettes as with arrays of PaletteSize integers. Default 1024.
MaxRecentCount specifies the number of palettes that 'Recents' folder holds. Default 32.
bShowToolz specifies the mode in which JP is shown initially - user or enchanced. Default true.

Ok. How to activate JP? As TJumboDialog is a child of TCommonDialog, you simply call Execute method. It returns true if user selected a palette, or false if he cancelled. Also, there is a UserOK property = true if user selected a palette after last execute call.

Idea is as follows. Call Execute method. Check if the user confirmed his selection - Execute returns True, or UserOK property is True. Then retrieve selection by properties like 'ResultPtr' or 'Recent[0]'. Scale palette if necessary using methods like 'DupResult' or 'ScalePalette'. Draw recent palettes using 'RecentCount' and 'Recent[i]'. Use recieved palettes as an arrays of integers of PaletteSize-size each.

Lets look at this example:
procedure TForm1.Button2Click(Sender: TObject);
var pal : PPalette; //pointer to array of colors [0..X]
 i : integer;
begin
 JumboDialog1.Execute; //executing dialog
    if JumboDialog1.UserOK then begin  //choice confirmed?
     pal := JumboDialog1.ResultPal; //pointer to palette
        for i := 0 to JumboDialog1.PaletteSize-1 do //go through all colors
        with Image1.Picture.Bitmap.Canvas do begin
         Pen.Color := _rgbflip( pal[i] ); // draw i-th color by line
            MoveTo( i,0 );
            LineTo( i,Image1.Height );
        end;
    end;
end;

Here we used 2 internal helpers:
type  TPalette = array [0..$FFFF] of integer;  PPalette = ^TPalette;
and 
function _rgbflip( c : integer ) : integer; //flips 0RGB to 0BGR for GDI usage
begin Result := ((c and $FF) shl 16) or( c and $FF00) or ((c shr 16) and $FF); end;

Ok, another example:
type TForm1 = class(TForm)  ...   pal : PPalette;    ... end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    if JumboDialog1.Execute then begin
     //copy selected palette to pal; memory allocated if necessary
      pal := JumboDialog1.DupResult( pal,JumboDialog1.PaletteSize,true );
      InvalidateRect( Self.Handle,nil,false );  //and repaint the form
    end;
end;

procedure TForm1.FormPaint(Sender: TObject);
var p : PPalette;
 i : integer;
begin
 if not JumboDialog1.UserOK then exit; //req repaint?
    p := JumboDialog1.DupPalette( pal,nil,Form1.Width,false );
    //scale palette to be equal to form
    for i := 0 to form1.Width-1 do with form1.Canvas do begin
        Pen.Color := p[i];
        MoveTo( i,0 );
        LineTo( i,form1.Height-1 );
    end;
    FreeMem( p ); //free allocated temp pal pointer
end;

Ok, dont know what to add anymore. Description of all the functions, methods and properties you will find below.

 
 

Advanced interface

As I told, you can manipulate on palette folders and add your own tools.
This topic will be described later by request (email).
 
 

Properties and methods description

Non-class helpers:
function _rgbflip( c : integer ) : integer; //flips 0RGB to 0BGR for GDI usage
type //for easy type-casting
  TPalette = array [0..$FFFF] of integer;  PPalette = ^TPalette; 

  public
    { Public declarations }
    property UserOK : boolean;
    // = True if user selected a palette after last Execute call
    property RecentCount : integer;
    // number of recent palettes
    property Recent[index : integer ] : pointer;
    // pointers to recent palettes
    // 0 - last selected, (RecentCount-1) - latest selected
    // This ptrs are valid only before next Execute call.
 property RecentBitmap : TBitmap;
    // pointer to a bitmap with recent palettes

    property ResultPtr : pointer;
    // pointer to selected palette
    // valid only after Execute method call if user selected,
    // and only before next Execute call.
    // Its a good idea to copy values from this ptr to some safe place
    // In its code, ResultPtr points to Recent[0]
    property ResultPal : PPalette;
    // casted pointer, validations are the same
    property Handle : Hwnd read GetHandle;
    // handle to JP window

 function Execute: Boolean;
    // executes the dialog. Returns true if user confirmed his choice.

    function StoreResult( dest : pointer ) : boolean;
    // stores palette, identified by Recent[0] into _dest.
    // Returns false if RecentCount = 0 (no recents)

    procedure ScalePalette( source,dest : pointer; src_width,dest_width : integer; flipRGB : boolean );
    // Helper funciton. Scales palette _source of _src_width colorst
    // to _dest. if flipRGB, it also flips RGB -> BGR for
    // GDI usage.

    function ScaleResult( dest : pointer; dest_width : integer; flipRGB : boolean ) : boolean;
    // Helper function. Scales result palette.

    function DupPalette( pal : ppalette; original_dest : pointer; destwidth : integer; flipRGB : boolean ) : pointer;
    // Helper function. Duplicated a palette _pal of _PalSize colors.
    // It reallocates _original_dest pointer using ReallocMem,
    // scales _palette to _destwidth colors, flips RGB if needed
    // and returns new pointer
    // Example: p := JD.DupPalette( mypal,nil,256,True )
    // - allocates new mem, scales palette _mypal to 256 colors,
    // flips RGB->BGR and stores new pointer in p

 function DupRecent( recent_index : integer; original_dest : pointer; destwidth : integer; flipRGB : boolean ) : pointer;
    // duplicates recent
    function DupResult( original_dest : pointer; destwidth : integer; flipRGB : boolean ) : pointer;
    // duplicates Recent[0]

    procedure Restart;
    // You can change PalSize, PalPath or other properties
    // at runtime. Then call Restart to take an effect.

  published
    property Caption : string;
    // caption of JP window
   property PalettePath : string;
    // a path to palette folder's bmp files, usualy relative like "Palettes\" (default)
    property PaletteSize : integer;
    // a palette size you want to use. JD/JP assume this palsize in all palette operations. So you will work with palettes as
 // with arrays of PaletteSize integers. Default 1024.
    property MaxRecentCount : integer;
    // specifies the number of palettes that 'Recents' folder holds. Default 32.
    property bShowToolz : boolean;
    // specifies the mode in which JP is shown initially - user or enchanced. Default true.
    property bLargeFoldersIcons : boolean;
 // specifies if folders icons are large or small
 property DefaultUserToolz : TWinControl;
    // specifies default programmer-added tools shown
    // on 'addition tools' pane.
    // use YOURPANEL.owner := JumboUserToolz;
    // to add more tools
 

// ADVANCHED SECTION
// will be described when I will be available...
    {API}
    property PalList : TListView;
    property EditMask : integer;

    property JumboUserToolz : TCoolBar;

    procedure ActivateToolOptions( your_options : TWinControl; title : string  );

    {this routines works with the items of __PalList}
    procedure SubstitutePalBitmap( index : integer; pal : pointer );
    procedure UpdatePalBitmap( index : integer );

    function GetActivePalette : PPalette;
    procedure ShowActivePalette( pal : ppalette; caption : string  );
    procedure RepaintActivePalette( everywhere : boolean );
    function CreatePalBitmap( bmp : TBitmap; width,height : integer; frame_width : integer; pal : ppalette ) : TBitmap;
 

    {Palette Folder = PF. Each PF, when saved, is just a bmp in _PalettePath_ directory}
    {Folders are numerated 0..GetFoldersCount-1}

    function GetFolderID( FolderName : string ) : integer;
    function GetFolderName( folder_id : integer ) : string;
    function GetActiveFolder : integer; {-1 - no folder; 0..Max - folder id}
    function GetFoldersCount : integer;

    function CreateNewFolder( DesiredFolderName : string ) : integer;
    procedure DeleteFolder( folder_id : integer );
    function ActivateFolder( folder_id : integer ) : boolean;

 procedure AddToFolder( folder_id : integer; p : Pointer );
    procedure ClearFolder( folder_id : integer );

    function GetFolderSize( folder_id : integer ) : integer;
    function GetFolderPalette( folder_id : integer; index : integer ) : PPalette;

 

Here I end this document. It will be completed later.
Be happy!

Created by Contact, july 2001
contact@mail.ur.ru