home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 5
/
DATAFILE_PDCD5.iso
/
utilities
/
v
/
vista
/
c
/
wins
< prev
Wrap
Text File
|
1996-02-01
|
26KB
|
1,052 lines
// **************************************************************************
// Copyright 1996 David Allison
//
// VV VV IIIIII SSSSS TTTTTT AA
// VV VV II SS TT AA AA
// VV VV II SSSS TT AA AA
// VV VV II SS TT AAAAAAAA
// VV IIIIII SSSS TT AA AA
//
// MULTI-THREADED C++ WIMP CLASS LIBRARY
// for RISC OS
// **************************************************************************
//
// P U B L I C D O M A I N L I C E N C E
// -------------------------------------------
//
// This library is copyright. You may not sell the library for
// profit, but you may sell products which use it providing
// those products are presented as executable code and are not
// libraries themselves. The library is supplied without any
// warranty and the copyright owner cannot be held responsible for
// damage resulting from failure of any part of this library.
//
// See the User Manual for details of the licence.
//
// *************************************************************************
#include "Vista:task.h"
#include "Vista:wins.h"
#include <kernel.h>
#include <swis.h>
#include "icon.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifndef __EASY_C
#include "Vista:myargs.h"
#endif
//
// An IconGrid
//
// this has a window with a vertical scroll bar and can be resized.
// It traps the open event from the Wimp and checks the current size
// of the window. If it can rearrange the icons it will.
//
IconGrid::IconGrid (Task *task, char *tname, int ticon, char *menu)
: Window (task, tname, menu)
{
init (ticon) ;
}
IconGrid::IconGrid (Window *w, char *tname, int ticon, char *menu)
: Window (w, tname, 0, menu)
{
init (ticon) ;
}
IconGrid::~IconGrid()
{
}
void IconGrid::init (int ticon)
{
_kernel_swi_regs r ;
_kernel_oserror *e ;
int block[40] ;
template_icon = new Icon (this, ticon) ;
template_icon->move_to (-1000,1000) ; // move the icon out of sight
block[0] = handle ;
block[1] = ticon ;
r.r[1] = (int)block ;
if ((e = _kernel_swi (Wimp_GetIconState, &r, &r)) != NULL)
throw (e) ;
template_button_type = (Icon::buttontype)((block[6] & 0xf000) >> 12) ;
Box *box = (Box*)&block[2] ;
icon_height = box->y1 - box->y0 ;
icon_width = box->x1 - box->x0 ;
num_rows = 0 ;
num_icons = 0 ;
current_column = 0 ;
current_row = 0 ;
num_columns = (x1 - x0 - ICONGRID_LEFT_MARGIN) / (icon_width + ICONGRID_HOR_GAP) ;
if (num_columns == 0)
num_columns = 1 ;
flag_set = NONE ;
Window::Info *inf = info() ;
min_height = inf->extent.y1 - inf->extent.y0 ;
}
void IconGrid::set_flag (flags flag)
{
#ifndef __EASY_C
int f = (int)flag_set ;
f |= (int)flag ;
flag_set = (flags)f ;
#else
flag_set |= (flags)flag ;
#endif
}
void IconGrid::clear_flag (flags flag)
{
#ifndef __EASY_C
int f = (int)flag_set ;
f &= ~(int)flag ;
flag_set = (flags)f ;
#else
flag_set |= (flags)flag ;
#endif
}
//
// add a new icon into the window. This will fill up the window from
// left to right taking a new row when a row is full.
//
Icon *IconGrid::insert_icon(char *text, void *ref)
{
int x, y ;
x = current_column * (icon_width + ICONGRID_HOR_GAP) + ICONGRID_LEFT_MARGIN ;
y = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
Icon *icon = new Icon (this, template_icon, x, -y, ref) ;
Box pos ;
icon->read_position (pos) ;
do_redraw (pos.x0, pos.y0, pos.x1, pos.y1) ; // redraw the window
icon->print (text) ;
num_icons++ ;
current_column++ ;
if (current_column == num_columns)
{
current_column = 0 ;
current_row++ ;
int new_height = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
if (new_height > min_height)
set_height (new_height) ;
}
if (flag_set & SORTED)
sort() ;
return icon ;
}
Icon *IconGrid::insert_icon(char *text, char *sprite, void *ref)
{
int x, y ;
x = current_column * (icon_width + ICONGRID_HOR_GAP) + ICONGRID_LEFT_MARGIN ;
y = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
Icon *icon = new Icon (this, template_icon, x, -y, ref) ;
Box pos ;
icon->read_position (pos) ;
do_redraw (pos.x0, pos.y0, pos.x1, pos.y1) ; // redraw the window
icon->print (text) ;
icon->change_sprite (sprite) ;
num_icons++ ;
current_column++ ;
if (current_column == num_columns)
{
current_column = 0 ;
current_row++ ;
int new_height = current_row * (icon_height + ICONGRID_VERT_GAP) + icon_height +ICONGRID_TOP_MARGIN ;
if (new_height > min_height)
set_height (new_height) ;
}
if (flag_set & SORTED)
sort() ;
return icon ;
}
void IconGrid::remove_icon(Icon *icon)
{
Window::remove_icon (icon) ;
if (!deleting)
{
num_icons-- ;
if (flag_set & SORTED)
sort() ;
}
}
void IconGrid::delete_icon (void *ref)
{
for (Icon *icon = icons ; icon != NULL ; icon = icon->next)
if (ref == icon->user_ref)
{
delete icon ;
break ;
}
}
//
// sort the icons in the grid using qsort
//
static int sort_compare (const void *i1, const void *i2)
{
const Icon **x = (const Icon**)i1 ;
const Icon **y = (const Icon**)i2 ;
#ifdef __EASY_C
return (*x)->compare(*y) ;
#else
Icon *i = (Icon*)*x ;
Icon *j = (Icon*)*y ;
return i->compare(j) ;
#endif
}
void IconGrid::sort()
{
int i ;
Icon *icon ;
Icon **buffer = new Icon *[num_icons] ;
for (icon = icons, i = 0 ; icon != NULL ; icon = icon->next)
if (icon != template_icon)
buffer[i++] = icon ;
qsort (buffer, num_icons, sizeof (Icon *), sort_compare) ;
icons = NULL ; // reset icons list
add_icon (template_icon) ; // add the template again
for (i = 0 ; i < num_icons ; i++) // put all the icons back
add_icon (buffer[i]) ;
rearrange() ;
delete [] buffer ;
}
void IconGrid::open(int x0, int y0, int x1, int y1, int scx, int scy, int behind)
{
Window::open (x0,y0,x1,y1,scx,scy,behind) ; // open the window
int nc = (x1 - x0 - ICONGRID_LEFT_MARGIN) / (icon_width + ICONGRID_HOR_GAP) ;
if (nc == 0)
nc = 1 ;
if (num_icons != 0 && nc != num_columns)
{
num_columns = nc ;
rearrange() ;
}
num_columns = nc ;
}
void IconGrid::click(int mx, int my, int buttons, int icon)
{
int click_factor ;
int double_factor ;
int drag_factor ;
switch (template_button_type)
{
case Icon::BCLICKDEBOUNCE:
click_factor = 1 ;
double_factor = 0 ;
drag_factor = 0 ;
break ;
case Icon::BDEBOUNCEDRAG:
default:
click_factor = 1 ;
double_factor = 0 ;
drag_factor = 16 ;
break ;
case Icon::BCLICKDRAGDOUBLE:
click_factor = 256 ;
double_factor = 1 ;
drag_factor = 16 ;
break ;
}
if (icon >= 0)
{
Icon *ic = Window::find_icon (icon) ;
if (buttons & (4 * drag_factor))
{
int count = 0 ;
int minx = 30000, maxx = 0, miny = 0, maxy = -30000;
Box pos ;
for (Icon *i = icons ; i != NULL ; i = i->next)
if (i->is_selected())
{
count++ ;
i->read_position(pos) ;
if (pos.x0 < minx) minx = pos.x0 ;
if (pos.x1 > maxx) maxx = pos.x1 ;
if (pos.y0 < miny) miny = pos.y0 ;
if (pos.y1 > maxy) maxy = pos.y1 ;
}
minx += x0 ;
miny += y1 ;
maxx += x0 ;
maxy += y1 ;
if (count > 1)
drag_selection (mx, my, buttons, minx, miny, maxx, maxy) ;