ONO::ToolBox::App

package ONO::ToolBox::App;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################

use strict;

use ONO::IO;
use ONO::FW::User::Init;

###############################################################################
# ONO
###############################################################################

#: This module helps building web applications that shall look and feel more or
#: less like common desktop applications.
#:
#: It is used by the ONO Media BookMaker, as well as by Morzino's Worksheet
#: Maker for example.

sub load {

#: Deprecated, may be reused in future.

}

sub menu {

#: Deprecated, may be reused in future.

}

sub topbar {

my (
$self,
$tops_ref,
$vars_ref,
) = @_;

#: Generate an applications top bar.
#:
#: -A disable if app_option var (link) is used
#: -d disabled
#: -D disble if vars_dir is empty
#: -F disble if vars_file is empty
#: -l link instead of hide/block (alternative for direct link: use link instead of ID)
#: -L link to app_option_XXX=1 instead of app_option=XXX (works with -l)
#: -u user required (disable if not logged in)

my @tops = @$tops_ref;
my %vars = %$vars_ref;

my $tops_count;

my $TOP;

foreach my $top (@tops) {
if ($top =~ /:/) {
$tops_count++;
my @tp = split(/:/,$top);
$tp[1] =~ s~ ~ ~g;
my ($ONCLICK,$CLASS,$disabled);
if (($tp[3] =~ /F/ && !$vars{'file'}) || ($tp[3] =~ /D/ && !$vars{'dir'})) {
$disabled = 1;
}
if (($tp[3] !~ /d/ || $tp[0] eq $vars{'app_option'}) && ($tp[3] !~ /u/ || $vars{'username'}) && ($tp[3] !~ /A/ || !$vars{'app_option'}) && !$disabled) {
$ONCLICK = qq~ onclick="ono_app_windows_close();onojs_block('ono_app_win_$tp[0]');"~;
$CLASS = "cursorlink";
if ($tp[3] =~ /l/) {
my $LINK = "app_option=$tp[0]";
if ($tp[3] =~ /L/) {
$LINK = "app_option_$tp[0]=1";
}
my $INPUT;
foreach my $opt ('dir','file') {
$INPUT .= qq~&$opt=$vars{$opt}~;
}
$ONCLICK = qq~ onclick="window.location='$ENV{'SCRIPT_NAME'}?mode=$vars{'mode'}&$LINK$INPUT';"~;
}
if ($tp[0] =~ m~^/~) {
$ONCLICK = qq~ onclick="window.location='$tp[0]';"~;
}
} else {
$CLASS = "trans30";
}
if ($tp[1] =~ /^(.*)\ \;\/(.*)$/) {
$tp[1] = qq~$1<span class="hide1300"> / $2</span>~;
}
my $HIDE = 800;
if ($tops_count > 2) {
$HIDE = 900;
if ($tops_count > 4) {
$HIDE = 1000;
if ($tops_count > 6) {
$HIDE = 1100;
}
}
}
$TOP .= qq~<td class="cole pad5_2 $CLASS"$ONCLICK><img class="block32" src="/ono/osr/images/icons/crystal/32x32/$tp[2].png" alt=""></td>
<td class="cole p2 nowrap $CLASS hide$HIDE" $ONCLICK>$tp[1]</td>
<td class="p5 hide800"></td>
~;
} else {
$TOP .= qq~<td class="pad10_2 br hide600"></td><td class="pad10_2 hide600"></td>~;
}
}

$TOP .= qq~<td class="w100"></td>~;

# if ($vars{'username'}) {
# my $IMG = ONO::FW::User::Init->profileimage($vars{'username'},32);
# $TOP .= qq~<td class="pad5_2">$IMG</td><td class="pad5_2 cole hide1000">$vars{'username'}</td>~;
# }

$TOP = qq~<div class="pad5_2"><table class="wide_table"><tr>$TOP</tr></table></div>~;

return $TOP;

}

sub topbar_script {

#: Generates JS code required by the topbar.

my $list_ref = $_[1];

my $SCRIPT;
foreach my $item (@$list_ref) {
if ($item =~ /:/) {
my @ip = split(/:/,$item);
$SCRIPT .= qq~onojs_hide('ono_app_win_$ip[0]');~;
}
}

return qq~\nfunction ono_app_windows_close(){$SCRIPT}\n~;

}

sub tools {

#: Generates the application tools sidebar.

my (
$self,
$tools_ref,
) = @_;

# Code contains a number of DIVs, these are actually REQUIRED, do NOT remove!

my @tools = @$tools_ref;

my ($TOOLS,$count);

foreach my $tool (@tools) {
if ($tool =~ /:/) {
my @tp = split(/:/,$tool);
if ($tp[0] eq "header") {
$TOOLS .= qq~</div></div><div class="box_blue flat_bottom pad5_0 center"><div class="hide800">$tp[1]</div><div class="hide block800 p5"></div></div><div class="box_fabric flat_top"><div class="inline w100">~;
} else {
my $IMG = "/ono/osr/images/icons/crystal/32x32/$tp[2].png";
if ($tp[2] =~ m~^/~) {
$IMG = $tp[2];
}
$TOOLS .= qq~<div class="bg_paper fl cursorlink" onmouseover="ono_app_tools_mouseover('$tp[0]');" onmouseout="ono_app_tools_mouseout('$tp[0]');">
<div id="ono_app_tools_tool_$tp[0]" class="bg_paper rel bo p5" onclick="ono_app_tools_select('$tp[0]');ono_app_tools_action('$tp[0]');">
<img class="block32 ml5 mr5" src="$IMG" alt="">
<div id="ono_app_tools_tooltip_$tp[0]_id" name="ono_app_tools_tooltip" class="abs box_yellow bo col3 pad5_0 small hide" style="top:36px;left:42px;z-index:999">$tp[1]</div>
</div>
</div>
~;
}
} else {
if ($tool eq "spacer") {
$TOOLS .= qq~</div></div><div class="p5"></div><div><div>~;
}
}
}

$TOOLS = qq~<div class="inline w100"><div><div>$TOOLS</div></div></div><div class="hide800" style="width:130px"></div>
<input type="hidden" id="ono_app_tools_selected_id" name="ono_app_tools_selected" value="">
~;

return $TOOLS;

}

sub tools_script {

#: Generates JS code required by the tools sidebar.

my $list_ref = $_[1];

my $SCRIPT;
foreach my $item (@$list_ref) {
if ($item =~ /:/) {
my @ip = split(/:/,$item);
$SCRIPT .= qq~onojs_class('ono_app_tools_tool_$ip[0]','bo p5');~;
}
}
return qq~\nfunction ono_app_tools_deselect_all(){$SCRIPT}\n~;

}

sub sideboxes {

#: Generates sideboxes.

my (
$self,
$boxes_ref,
$GLOBAL,
$side_ref,
) = @_;

my $BOXES;

my %side = %$side_ref;

foreach my $box (@$boxes_ref) {
if ($box =~ /:/) {
my @bp = split(/:/,$box);
$BOXES .= &sidebox("",$bp[0],"hide",$bp[1],qq~<div>$GLOBAL</div><div>$side{$bp[0]}</div>~);
}
}

return $BOXES;

}

sub sidebox {

#: Generates a single sidebox.

my (
$self,
$ID,
$CLASS,
$TITLE,
$BOX,
) = @_;

return qq~<div id="ono_app_sidebox_$ID" class="$CLASS">
<div class="bg_black cole small">
<div class="ml10">$TITLE</div>
</div>
<div class="bg_paper bo p10">
$BOX
</div>
</div>
~;

}

sub sidebox_script {

#: Generates JS code required by sideboxes.

my $list_ref = $_[1];

my $SCRIPT;
foreach my $item (@$list_ref) {
if ($item =~ /:/) {
my @ip = split(/:/,$item);
$SCRIPT .= qq~onojs_hide('ono_app_sidebox_$ip[0]');~;
}
}
return qq~\nfunction ono_app_sidebar_close_all(){$SCRIPT}\n~;

}

sub window {

my (
$self,
$ID,
$COLOR,
$TITLE,
$BOX,
$switches,
) = @_;

#: Generates an application window.
#:
#: -H unhide (hide is default)
#: -w wide (min 480px)
#: -W wider (min 640px)

my ($hide,$COLOR2);

if ($COLOR =~ /^(green|yellow|red)$/) {
$COLOR2 = $COLOR;
}
if ($COLOR =~ /^(black)$/) {
$COLOR2 = "cole";
}
if ($switches !~ /H/) {
$hide = " hide";
}

my $min_width = 240;
if ($switches =~ /w/) {
$min_width = 480;
}
if ($switches =~ /W/) {
$min_width = 640;
}

return qq~<div id="ono_app_win_$ID" class="box_$COLOR$hide rel" style="min-width:${min_width}px;left:10px;z-index:999">
<a href="javascript:void();" onclick="onojs_hide('ono_app_win_$ID');"><img class="close" src="/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="close"></a>
<h3 class="$COLOR2">$TITLE</h3>
<div class="box_paper">$BOX</div>
</div>
~;

}

sub render {

my (
$self,
$TOP,
$LEFT,
$MAIN,
$RIGHT,
$WIN,
$INPUT,
$BLK_ref,
) = @_;

#: Render the entire application, using the different parts of the application as input.

my %BLK = %$BLK_ref;

if ($TOP) {
$TOP = qq~<div class="bg_black p5">$TOP</div>~;
}
if ($LEFT) {
$LEFT = qq~<div class="bg_black p10" style="background-color:#666666">$LEFT</div>~;
}
if ($MAIN) {
$MAIN = qq~<div class="bg_fabric p10 bl br">$MAIN</div>~;
}
if ($RIGHT) {
$RIGHT = qq~<div class="bg_black p10" style="background-color:#666666">$RIGHT</div>~;
}

return qq~<form method="post" action="$ENV{'SCRIPT_NAME'}">
$INPUT
<div class="rel bg_black">
$TOP
<div class="p2 bg_fabric trans50"></div>
<table class="wide_table" style="background-color:#666666">
<tr class="vtop">
<td class="p0">$LEFT</td>
<td class="p0 w100">
<div class="fl w66 w100_1100 bg_fabric"><div class="inline w100">$MAIN</div></div>
<div class="fl w33 w100_1100"><div class="inline w100">$RIGHT</div></div>
</td>
</tr>
</table>
<div class="abs" style="top:100px;left:150px">$WIN</div>
</div>
<div class="rel bg_black p5" style="background-color:#666666"></div>
</form>
~;

}

sub script {

my (
$self,
$SCRIPT,
) = @_;

#: The main application JS code.

# ono_app_sidebar_close_all();

return qq~<script>
function ono_app_tools_select(tool) {
ono_app_windows_close();
ono_app_tools_deselect_all();
onojs_class('ono_app_tools_tool_'+tool,'bg_black rel bo p5');
onojs_block('ono_app_sidebox_'+tool);
onojs_setvalue('ono_app_tools_selected_id',tool);
}
function ono_app_tools_mouseover(tool) {
onojs_class('ono_app_tools_tool_'+tool,'bg_black rel bo p5');
onojs_block('ono_app_tools_tooltip_'+tool+'_id');
}
function ono_app_tools_mouseout(tool) {
if (onojs_getvalue('ono_app_tools_selected_id') === tool) {
onojs_class('ono_app_tools_tool_'+tool,'bg_black rel bo p5');
} else {
onojs_class('ono_app_tools_tool_'+tool,'bg_paper rel bo p5');
}
onojs_hide_by_name('ono_app_tools_tooltip');
}
$SCRIPT
</script>
~;

}

###############################################################################
# end of script
###############################################################################

1;

__END__