/*-
* Copyright (c) 1997-2002 The Protein Laboratory, University of Copenhagen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#include "apricot.h"
#include "Window.h"
#include "Menu.h"
#include "Icon.h"
#include "Application.h"
#include <Window.inc>
#ifdef __cplusplus
extern "C" {
#endif
#undef my
#define inherited CWidget->
#define my ((( PWindow) self)-> self)
#define var (( PWindow) self)
void
Window_init( Handle self, HV * profile)
{
dPROFILE;
SV * sv;
inherited init( self, profile);
opt_set( optSystemSelectable);
opt_assign( optOwnerIcon, pget_B( ownerIcon));
opt_assign( optMainWindow, pget_B( mainWindow));
my-> set_icon( self, pget_H( icon));
my-> menuColorIndex( self, true, ciFore, pget_i( menuColor) );
my-> menuColorIndex( self, true, ciBack, pget_i( menuBackColor) );
my-> menuColorIndex( self, true, ciHiliteText, pget_i( menuHiliteColor) );
my-> menuColorIndex( self, true, ciHilite, pget_i( menuHiliteBackColor) );
my-> menuColorIndex( self, true, ciDisabledText, pget_i( menuDisabledColor) );
my-> menuColorIndex( self, true, ciDisabled, pget_i( menuDisabledBackColor));
my-> menuColorIndex( self, true, ciLight3DColor, pget_i( menuLight3DColor) );
my-> menuColorIndex( self, true, ciDark3DColor, pget_i( menuDark3DColor) );
SvHV_Font( pget_sv( menuFont), &Font_buffer, "Window::init");
my-> set_menu_font ( self, Font_buffer);
if ( SvTYPE( sv = pget_sv( menuItems)) != SVt_NULL)
my-> set_menuItems( self, sv);
my-> set_modalResult( self, pget_i( modalResult));
my-> set_modalHorizon( self, pget_B( modalHorizon));
CORE_INIT_TRANSIENT(Window);
}
void
Window_cancel( Handle self)
{
my-> set_modalResult ( self, mbCancel);
my-> end_modal( self);
}
void
Window_ok( Handle self)
{
my-> set_modalResult ( self, mbOK);
my-> end_modal( self);
}
void
Window_cleanup( Handle self)
{
if ( var-> modal) my-> cancel( self);
my-> detach( self, var-> menu, true);
var-> menu = nilHandle;
inherited cleanup( self);
}
void Window_update_sys_handle( Handle self, HV * profile)
{
dPROFILE;
var-> widgetClass = wcWindow;
if (!(
pexist( owner) ||
pexist( syncPaint) ||
pexist( taskListed) ||
pexist( borderIcons) ||
pexist( onTop) ||
pexist( borderStyle)
)) return;
if ( pexist( owner)) my-> cancel_children( self);
if ( !apc_window_create( self,
pexist( owner ) ? pget_H( owner ) : var-> owner ,
pexist( syncPaint) ? pget_B( syncPaint) : my-> get_syncPaint( self),
pexist( borderIcons) ? pget_i( borderIcons) : my-> get_borderIcons( self),
pexist( borderStyle) ? pget_i( borderStyle) : my-> get_borderStyle( self),
pexist( taskListed) ? pget_B( taskListed) : my-> get_taskListed( self),
pexist( windowState) ? pget_i( windowState) : my-> get_windowState( self),
pexist( onTop) ? pget_B( onTop) : -1, /* This is way better. I should've thought of this before! */
!( pexist( originDontCare) && pget_B( originDontCare)),
!( pexist( sizeDontCare) && pget_B( sizeDontCare))
))
croak("Cannot create window");
pdelete( borderStyle);
pdelete( borderIcons);
pdelete( syncPaint);
pdelete( taskListed);
pdelete( windowState);
pdelete( onTop);
}
void Window_handle_event( Handle self, PEvent event)
{
#define evOK ( var-> evStack[ var-> evPtr - 1])
#define objCheck if ( var-> stage > csNormal) return
switch (event-> cmd)
{
case cmColorChanged:
if ( event-> gen. source == var-> menu) {
var-> menuColor[ event-> gen. i] = apc_menu_get_color( var-> menu, event-> gen. i);
return;
}
break;
case cmFontChanged:
if ( event-> gen. source == var-> menu)
{
apc_menu_get_font( var-> menu, &var-> menuFont);
return;
}
break;
case cmExecute:
my-> notify( self, "<s", "Execute");
break;
case cmEndModal:
my-> notify( self, "<s", "EndModal");
break;
case cmActivate:
if ( var-> owner)
PWidget( var-> owner)-> currentWidget = self;
my-> notify( self, "<s", "Activate");
break;
case cmDeactivate:
my-> notify( self, "<s", "Deactivate");
break;
case cmWindowState:
my-> notify( self, "<si", "WindowState", event-> gen. i);
break;
case cmDelegateKey:
#define leave { my-> clear_event( self); return; }
if ( var-> modal && event-> key. subcmd == 0)
{
Event ev = *event;
ev. key. cmd = cmTranslateAccel;
if ( !my-> message( self, &ev)) leave;
if ( my-> first_that( self, (void*)accel_notify, &ev)) leave;
ev. key. cmd = cmDelegateKey;
ev. key. subcmd = 1;
if ( my-> first_that( self, (void*)accel_notify, &ev)) leave;
}
objCheck;
break;
case cmTranslateAccel:
if ( event-> key. key == kbEsc && var-> modal)
{
my-> cancel( self);
my-> clear_event( self);
return;
}
break;
}
inherited handle_event ( self, event);
}
void
Window_end_modal( Handle self)
{
Event ev = { cmEndModal};
if ( !var-> modal) return;
apc_window_end_modal( self);
ev. gen. source = self;
my-> message( self, &ev);
}
int
Window_get_modal( Handle self)
{
return var-> modal;
}
SV *
Window_get_client_handle( Handle self)
{
char buf[ 256];
snprintf( buf, 256, "0x%08lx", apc_window_get_client_handle( self));
return newSVpv( buf, 0);
}
Handle
Window_get_modal_window( Handle self, int modalFlag, Bool next)
{
if ( modalFlag == mtExclusive) {
return next ? var-> nextExclModal : var-> prevExclModal;
} else if ( modalFlag == mtShared) {
return next ? var-> nextSharedModal : var-> prevSharedModal;
}
return nilHandle;
}
Handle
Window_get_horizon( Handle self)
{
/* self trick is appropriate here;
don't bump into it accidentally */
self = var-> owner;
while ( self != application && !my-> get_modalHorizon( self))
self = var-> owner;
return self;
}
void
Window_exec_enter_proc( Handle self, Bool sharedExec, Handle insertBefore)
{
if ( var-> modal)
return;
if ( sharedExec) {
Handle mh = my-> get_horizon( self);
var-> modal = mtShared;
/* adding new modal horizon in global mh-list */
if ( mh != application && !PWindow(mh)-> nextSharedModal)
list_add( &PApplication( application)-> modalHorizons, mh);
if (( var-> nextSharedModal = insertBefore)) {
/* inserting window in between of modal list */
Handle *iBottom = ( mh == application) ?
&PApplication(mh)-> sharedModal : &PWindow(mh)-> nextSharedModal;
var-> prevSharedModal = PWindow( insertBefore)-> prevSharedModal;
if ( *iBottom == insertBefore)
*iBottom = self;
} else {
/* inserting window on top of modal list */
Handle *iTop = ( mh == application) ?
&PApplication(mh)-> topSharedModal : &PWindow(mh)-> topSharedModal;
if ( *iTop)
PWindow( *iTop)-> nextSharedModal = self;
else {
if ( mh == application)
PApplication(mh)-> sharedModal = self;
else
PWindow(mh)-> nextSharedModal = self;
}
var-> prevSharedModal = *iTop;
*iTop = self;
}
}
/* end of shared exec */
else
/* start of exclusive exec */
{
PApplication app = ( PApplication) application;
var-> modal = mtExclusive;
if (( var-> nextExclModal = insertBefore)) {
var-> prevExclModal = PWindow( insertBefore)-> prevExclModal;
if ( app-> exclModal == insertBefore)
app-> exclModal = self;
} else {
var-> prevExclModal = app-> topExclModal;
if ( app-> exclModal)
PWindow( app-> topExclModal)-> nextExclModal = self;
else
app-> exclModal = self;
app-> topExclModal = self;
}
}
}
void
Window_exec_leave_proc( Handle self)
{
if ( !var-> modal)
return;
if ( var-> modal == mtShared) {
Handle mh = my-> get_horizon( self);
if ( var-> prevSharedModal) {
PWindow prev = ( PWindow) var-> prevSharedModal;
if ( prev-> nextSharedModal == self)
prev-> nextSharedModal = var-> nextSharedModal;
}
if ( var-> nextSharedModal) {
PWindow next = ( PWindow) var-> nextSharedModal;
if ( next-> prevSharedModal == self)
next-> prevSharedModal = var-> prevSharedModal;
}
if ( mh == application) {
PApplication app = ( PApplication) application;
if ( app) {
if ( app-> sharedModal == self)
app-> sharedModal = var-> nextSharedModal;
if ( app-> topSharedModal == self)
app-> topSharedModal = var-> prevSharedModal;
}
} else {
PWindow win = ( PWindow) mh;
if ( win-> nextSharedModal == self)
win-> nextSharedModal = var-> nextSharedModal;
if ( win-> topSharedModal == self)
win-> topSharedModal = var-> prevSharedModal;
/* removing horizon from global mh-list */
if ( !win-> nextSharedModal)
list_delete( &PApplication(application)-> modalHorizons, mh);
}
var-> prevSharedModal = var-> nextSharedModal = nilHandle;
} /* end of shared exec */
else
/* start of exclusive exec */
{
PApplication app = ( PApplication) application;
if ( var-> prevExclModal) {
PWindow prev = ( PWindow) var-> prevExclModal;
if ( prev-> nextExclModal == self)
prev-> nextExclModal = var-> nextExclModal;
}
if ( var-> nextExclModal) {
PWindow next = ( PWindow) var-> nextExclModal;
if ( next-> prevExclModal == self)
next-> prevExclModal = var-> prevExclModal;
}
if ( app) {
if ( app-> exclModal == self)
app-> exclModal = var-> nextExclModal;
if ( app-> topExclModal == self)
app-> topExclModal = var-> prevExclModal;
}
var-> prevExclModal = var-> nextExclModal = nilHandle;
}
var-> modal = mtNone;
}
void
Window_cancel_children( Handle self)
{
protect_object( self);
if ( my-> get_modalHorizon( self)) {
Handle next = var-> nextSharedModal;
while ( next) {
CWindow( next)-> cancel( next);
next = var-> nextSharedModal;
}
} else {
Handle mh = my-> get_horizon( self);
Handle next = ( mh == application) ?
PApplication(mh)-> sharedModal :
PWindow(mh)-> nextSharedModal;
while ( next) {
if ( Widget_is_child( next, self)) {
CWindow( next)-> cancel( next);
next = PWindow(mh)-> nextSharedModal;
} else
next = PWindow(next)-> nextSharedModal;
}
}
unprotect_object( self);
}
int
Window_execute( Handle self, Handle insertBefore)
{
if ( var-> modal)
return mbCancel;
protect_object( self);
if ( insertBefore
&& ( insertBefore == self
|| !kind_of( insertBefore, CWindow)
|| PWindow( insertBefore)-> modal != mtExclusive))
insertBefore = nilHandle;
if ( !apc_window_execute( self, insertBefore))
var-> modalResult = mbCancel;
unprotect_object( self);
return var-> modalResult;
}
Bool
Window_execute_shared( Handle self, Handle insertBefore)
{
if ( var-> modal || var-> nextSharedModal) return false;
if ( insertBefore &&
(( insertBefore == self) ||
( !kind_of( insertBefore, CWindow)) ||
( PWindow( insertBefore)-> modal != mtShared) ||
( CWindow( insertBefore)-> get_horizon( insertBefore) != my-> get_horizon( self))))
insertBefore = nilHandle;
return apc_window_execute_shared( self, insertBefore);
}
Bool
Window_modalHorizon( Handle self, Bool set, Bool modalHorizon)
{
if ( !set)
return is_opt( optModalHorizon);
if ( is_opt( optModalHorizon) == modalHorizon) return false;
my-> cancel_children( self);
opt_assign( optModalHorizon, modalHorizon);
return modalHorizon;
}
int
Window_modalResult ( Handle self, Bool set, int modalResult)
{
if ( !set)
return var-> modalResult;
return var-> modalResult = modalResult;
}
static void
activate( Handle self, Bool ok)
{
if ( var-> stage == csNormal) {
if ( ok)
apc_window_activate( self);
else
if ( apc_window_is_active( self))
apc_window_activate( nilHandle);
}
}
Bool
Window_focused( Handle self, Bool set, Bool focused)
{
if ( set)
activate( self, focused);
return inherited focused( self, set, focused);
}
void Window_set( Handle self, HV * profile)
{
dPROFILE;
Bool owner_icon = false;
if ( pexist( menuFont)) {
SvHV_Font( pget_sv( menuFont), &Font_buffer, "Window::set");
my-> set_menu_font( self, Font_buffer);
pdelete( menuFont);
}
if ( pexist( owner)) {
owner_icon = pexist( ownerIcon) ? pget_B( ownerIcon) : my-> get_ownerIcon( self);
pdelete( ownerIcon);
}
if ( pexist( frameOrigin) || pexist( frameSize)) {
Bool io = 0, is = 0;
Point o, s;
if ( pexist( frameOrigin)) {
int set[2];
prima_read_point( pget_sv( frameOrigin), set, 2, "Array panic on 'frameOrigin'");
pdelete( frameOrigin);
o. x = set[0];
o. y = set[1];
io = 1;
} else {
o.x = o. y = 0;
}
if ( pexist( frameSize)) {
int set[2];
prima_read_point( pget_sv( frameSize), set, 2, "Array panic on 'frameSize'");
pdelete( frameSize);
s. x = set[0];
s. y = set[1];
is = 1;
} else {
s.x = s. y = 0;
}
if ( is && io)
apc_widget_set_rect( self, o. x, o. y, s. x, s. y);
else if ( io)
my-> set_frameOrigin( self, o);
else
my-> set_frameSize( self, s);
}
inherited set( self, profile);
if ( owner_icon) {
my-> set_ownerIcon( self, 1);
opt_set( optOwnerIcon);
}
}
static Bool
icon_notify ( Handle self, Handle child, Handle icon)
{
if ( kind_of( child, CWindow) && (( PWindow) child)-> options. optOwnerIcon) {
(( PWindow) child)-> self-> set_icon( child, icon);
(( PWindow) child)-> options. optOwnerIcon = 1;
}
return false;
}
Handle
Window_icon( Handle self, Bool set, Handle icon)
{
if ( var-> stage > csFrozen) return nilHandle;
if ( !set) {
if ( apc_window_get_icon( self, nilHandle)) {
HV * profile = newHV();
Handle i = Object_create( "Prima::Icon", profile);
sv_free(( SV *) profile);
apc_window_get_icon( self, i);
--SvREFCNT( SvRV((( PAnyObject) i)-> mate));
return i;
} else
return nilHandle;
}
if ( icon && !kind_of( icon, CImage)) {
warn("Illegal object reference passed to Window::icon");
return nilHandle;
}
my-> first_that( self, (void*)icon_notify, (void*)icon);
apc_window_set_icon( self, icon);
opt_clear( optOwnerIcon);
return nilHandle;
}
Bool
Window_mainWindow( Handle self, Bool set, Bool mainWindow)
{
if ( !set)
return is_opt( optMainWindow);
opt_assign( optMainWindow, mainWindow);
return false;
}
Handle
Window_menu( Handle self, Bool set, Handle menu)
{
if ( var-> stage > csFrozen) return nilHandle;
if ( !set)
return var-> menu;
if ( menu && !kind_of( menu, CMenu)) return nilHandle;
if ( menu && (( PMenu) menu)-> owner != self)
my-> set_menuItems( self, ((( PMenu) menu)-> self)-> get_items( menu, ""));
else {
apc_window_set_menu( self, menu);
var-> menu = menu;
if ( menu)
{
int i;
ColorSet menuColor;
memcpy( menuColor, var-> menuColor, sizeof( ColorSet));
for ( i = 0; i < ciMaxId + 1; i++)
apc_menu_set_color( menu, menuColor[ i], i);
memcpy( var-> menuColor, menuColor, sizeof( ColorSet));
apc_menu_set_font( menu, &var-> menuFont);
}
}
return nilHandle;
}
SV *
Window_menuItems( Handle self, Bool set, SV * menuItems)
{
dPROFILE;
if ( var-> stage > csFrozen) return nilSV;
if ( !set)
return var-> menu ? CMenu( var-> menu)-> get_items( var-> menu, "") : nilSV;
if ( var-> menu == nilHandle) {
if ( SvTYPE( menuItems)) {
HV * profile = newHV();
pset_sv( items, menuItems);
pset_H ( owner, self);
pset_i ( selected, false);
my-> set_menu( self, create_instance( "Prima::Menu"));
sv_free(( SV *) profile);
}
} else
CMenu( var-> menu)-> set_items( var-> menu, menuItems);
return menuItems;
}
Color
Window_menuColorIndex( Handle self, Bool set, int index, Color color)
{
if (( index < 0) || ( index > ciMaxId)) return clInvalid;
if ( !set)
return var-> menuColor[ index];
if ((( color & clSysFlag) != 0) && (( color & wcMask) == 0)) color |= wcMenu;
var-> menuColor[ index] = color;
if ( var-> menu) apc_menu_set_color( var-> menu, color, index);
return clInvalid;
}
void
Window_set_menu_font( Handle self, Font font)
{
apc_font_pick( self, &font, &var-> menuFont);
if ( var-> menu) apc_menu_set_font( var-> menu, &var-> menuFont);
}
Font
Window_get_menu_font( Handle self)
{
return var-> menuFont;
}
Font
Window_get_default_menu_font( char * dummy)
{
Font f;
apc_menu_default_font( &f);
return f;
}
Bool
Window_onTop( Handle self, Bool set, Bool onTop)
{
HV * profile;
if ( !set)
return apc_window_get_on_top( self);
profile = newHV();
pset_i( onTop, onTop);
my-> set( self, profile);
sv_free(( SV *) profile);
return true;
}
Bool
Window_ownerIcon( Handle self, Bool set, Bool ownerIcon)
{
if ( !set)
return is_opt( optOwnerIcon);
opt_assign( optOwnerIcon, ownerIcon);
if ( is_opt( optOwnerIcon) && var-> owner) {
Handle icon = ( var-> owner == application) ?
CApplication( application)-> get_icon( application) :
CWindow( var-> owner)-> get_icon( var-> owner);
my-> set_icon( self, icon);
opt_set( optOwnerIcon);
}
return false;
}
Bool
Window_process_accel( Handle self, int key)
{
return var-> modal ? my-> first_that_component( self, (void*)find_accel, &key)
: inherited process_accel( self, key);
}
void Window_on_execute( Handle self) {}
void Window_on_endmodal( Handle self) {}
void Window_on_activate( Handle self) {}
void Window_on_deactivate( Handle self) {}
void Window_on_windowstate( Handle self, int windowState) {}
Bool
Window_transparent( Handle self, Bool set, Bool transparent)
{
return false;
}
int
Window_borderIcons( Handle self, Bool set, int borderIcons)
{
HV * profile;
if ( !set)
return apc_window_get_border_icons( self);
profile = newHV();
pset_i( borderIcons, borderIcons);
my-> set( self, profile);
sv_free(( SV *) profile);
return nilHandle;
}
int
Window_borderStyle( Handle self, Bool set, int borderStyle)
{
HV * profile;
if ( !set)
return apc_window_get_border_style( self);
profile = newHV();
pset_i( borderStyle, borderStyle);
my-> set( self, profile);
sv_free(( SV *) profile);
return nilHandle;
}
Point
Window_frameOrigin( Handle self, Bool set, Point frameOrigin)
{
if ( !set)
return apc_widget_get_pos( self);
apc_widget_set_pos( self, frameOrigin.x, frameOrigin.y);
return frameOrigin;
}
Point
Window_frameSize( Handle self, Bool set, Point frameSize)
{
if ( !set)
return apc_widget_get_size( self);
apc_widget_set_size( self, frameSize.x, frameSize.y);
return frameSize;
}
Point
Window_origin( Handle self, Bool set, Point origin)
{
if ( !set)
return apc_window_get_client_pos( self);
apc_window_set_client_pos( self, origin.x, origin.y);
return origin;
}
Rect
Window_rect( Handle self, Bool set, Rect r)
{
if ( !set)
return inherited rect( self, set, r);
apc_window_set_client_rect( self, r. left, r. bottom, r. right - r. left, r. top - r. bottom);
return r;
}
Bool
Window_selected( Handle self, Bool set, Bool selected)
{
if (!set)
return inherited get_selected( self);
activate( self, selected);
inherited selected( self, set, selected);
return selected;
}
Point
Window_size( Handle self, Bool set, Point size)
{
if ( !set)
return apc_window_get_client_size( self);
apc_window_set_client_size( self, size.x, size.y);
return size;
}
Bool
Window_taskListed( Handle self, Bool set, Bool taskListed)
{
HV * profile;
if ( !set)
return apc_window_get_task_listed( self);
profile = newHV();
pset_i( taskListed, taskListed);
my-> set( self, profile);
sv_free(( SV *) profile);
return nilHandle;
}
SV *
Window_text( Handle self, Bool set, SV * text)
{
SV *ret = inherited text( self, set, text);
if (set)
apc_window_set_caption( self, var-> text, is_opt( optUTF8_text));
return ret;
}
Bool
Window_validate_owner( Handle self, Handle * owner, HV * profile)
{
dPROFILE;
*owner = pget_H( owner);
if ( *owner != application && !kind_of( *owner, CWidget)) return false;
return inherited validate_owner( self, owner, profile);
}
int
Window_windowState( Handle self, Bool set, int windowState)
{
if ( !set)
return apc_window_get_window_state( self);
return ( int) apc_window_set_window_state( self, windowState);
}
#ifdef __cplusplus
}
#endif