\n";
}
return False;
}
/**
* Calculates the vertical position based on the time
*
* workday start- and end-time, is taken into account, as well as timeGrids px_m - minutes per pixel param
* @param int $time in minutes
* @return int position in pixels
*/
function time2pos($time)
{
// time before workday => condensed in the first row
if ($this->wd_start > 0 && $time < $this->wd_start)
{
$pos = round($time / $this->px_m / $this->wd_start);
}
// time after workday => condensed in the last row
elseif ($this->wd_end < 24*60 && $time > $this->wd_end+2*$this->granularity_m)
{
$pos = $this->time2pos($this->wd_end+2*$this->granularity_m) +
round(($time - ($this->wd_end+2*$this->granularity_m)) / $this->px_m /
(24*60 - ($this->wd_end+2*$this->granularity_m)));
}
// time during the workday => 2. row on (= + granularity)
else
{
$pos = round(($time - $this->wd_start + $this->granularity_m) / $this->px_m);
}
if ($this->debug > 3) $this->bo->debug_message('uiviews::time2pos(%1)=%2',False,$time,$pos);
return $pos;
}
/**
* Calculates the height of a differenc between 2 times
*
* workday start- and end-time, is taken into account, as well as timeGrids px_m - minutes per pixel param
* @param int $start time in minutes
* @param int $end time in minutes
* @param int $minimum=0 minimum height
* @return int height in pixel
*/
function times2height($start,$end,$minimum=0)
{
$height = $this->time2pos($end) - $this->time2pos($start);
if ($this->debug > 3) $this->bo->debug_message('uiviews::times2height(%1,%2,min=%3)=%4',False,$start,$end,$minimum,$height);
return $height >= $minimum ? $height : $minimum;
}
/**
* Creates a grid with rows for the time, columns for (multiple) days containing events
*
* Uses the dayColWidget to display each day.
*
* @param $daysEvents array with subarrays of events for each day to show, day as YYYYMMDD as key
* @param int $width width of the widget
* @param int $granularity_m granularity in minutes of the rows
* @param int/float $px_m minutes per pixel - pixel in minutes ;-)
* @param string $indent string for correct indention
* @param string $title title of the time-grid
*/
function timeGridWidget($daysEvents,$width,$granularity_m=30,$px_m=1.7,$indent='',$title='')
{
if ($this->debug > 1 || $this->debug==='timeGridWidget') $this->bo->debug_message('uiviews::timeGridWidget(events=%1,width=%2,granularity_m=%3,px_m=%4,)',True,$daysEvents,$width,$granularity_m,$px_m);
$this->px_m = $px_m; // for time2pos()
$this->granularity_m = $granularity_m;
$html = $indent.'
'."\n";
if ($title)
{
$html .= $indent."\t".'
'.$title."
\n";
}
$off = True; // Off-row means a different bgcolor
for ($t = 0; $t < 24*60; $t += $inc)
{
$inc = $granularity_m;
if (!$t)
{
$inc = $this->wd_start;
}
elseif ($t > $this->wd_end)
{
$inc = 24*60 - $this->wd_end;
}
$html .= $indent."\t".'
\n"; // calDayCol
return $html;
}
/**
* Creates colunm for non-overlaping (!) events
*
* Uses the eventWidget to display each event.
*
* @param array $events of events to show
* @param int $left start of the widget
* @param int $width width of the widget
* @param string $indent string for correct indention
*/
function eventColWidget($events,$left,$width,$indent)
{
if ($this->debug > 1 || $this->debug==='eventColWidget') $this->bo->debug_message('uiviews::eventColWidget(%1,left=%2,width=%3,)',False,$events,$left,$width);
$html = $indent.'
\n";
return $html;
}
/**
* Shows one event
*
* The display of the event and it's tooltip is done via the event_widget.tpl template
*
* @param $event array with the data of event to show
* @param $width int width of the widget
* @param string $indent string for correct indention
*/
function eventWidget($event,$width,$indent)
{
if ($this->debug > 1 || $this->debug==='eventWidget') $this->bo->debug_message('uiviews::eventWidget(%1)',False,$event);
static $tpl = False;
if (!$tpl)
{
$tpl = $GLOBALS['phpgw']->template;
$tpl->set_file('event_widget_t','event_widget.tpl');
$tpl->set_block('event_widget_t','event_widget');
$tpl->set_block('event_widget_t','event_tooltip');
}
if ($event['start_m'] == 0 && $event['end_m'] == 24*60-1)
{
$timespan = lang('all day');
}
else
{
foreach(array($event['start_m'],$event['end_m']) as $minutes)
{
$timespan[] = $GLOBALS['phpgw']->common->formattime(sprintf('%02d',$minutes/60),sprintf('%02d',$minutes%60));
}
$timespan = implode(' - ',$timespan);
}
$icons = $this->event_icons($event);
$cats = $this->bo->categories($event['category'],$color);
// these values control varius aspects of the geometry of the eventWidget
$small_trigger_width = 120 + 20*count($icons);
$corner_radius=$width > $small_trigger_width ? 10 : 5;
$header_height=$width > $small_trigger_width ? 19 : 12; // multi_3 icon has a height of 19=16+2*1padding+1border !
$height = $this->times2height($event['start_m'],$event['end_m'],$header_height);
$body_height = max(0,$height - $header_height - $corner_radius);
$border=1;
$headerbgcolor = $color ? $color : '#808080';
// the body-colors (gradient) are calculated from the headercolor, which depends on the cat of an event
$bodybgcolor1 = $this->brighter($headerbgcolor,170);
$bodybgcolor2 = $this->brighter($headerbgcolor,220);
$tpl->set_var(array(
// event-content, some of it displays only if it really has content or is needed
'header_icons' => $width > $small_trigger_width ? implode("",$icons) : '',
'body_icons' => $width > $small_trigger_width ? '' : implode("\n",$icons).' ',
'icons' => implode("\n",$icons),
'header' => $timespan,
'title' => $this->html->htmlspecialchars($event['title']),
'description' => nl2br($this->html->htmlspecialchars($event['description'])),
'location' => $this->add_nonempty($event['location'],lang('Location')),
'participants' => count($event['participants']) == 1 && isset($event['participants'][$this->user]) ? '' :
$this->add_nonempty($this->bo->participants($event['participants']),lang('Participants'),True),
'multidaytimes' => !$event['multiday'] ? '' :
$this->add_nonempty($GLOBALS['phpgw']->common->show_date($this->bo->date2ts($event['start'])),lang('Start Date/Time')).
$this->add_nonempty($GLOBALS['phpgw']->common->show_date($this->bo->date2ts($event['end'])),lang('End Date/Time')),
'category' => $this->add_nonempty($cats,lang('Category')),
// the tooltip is based on the content of the actual widget, this way it takes no extra bandwidth/volum
// 'tooltip' => $this->html->tooltip(False,False,array('BorderWidth'=>0,'Padding'=>0)),
// various aspects of the geometry or style
'corner_radius' => $corner_radius.'px',
'header_height' => $header_height.'px',
'body_height' => $body_height.'px',
'height' => $height,
'width' => ($width-20).'px',
'border' => $border,
'bordercolor' => $headerbgcolor,
'headerbgcolor' => $headerbgcolor,
'bodybackground' => 'url('.$GLOBALS['phpgw_info']['server']['webserver_url'].
'/calendar/inc/gradient.php?color1='.urlencode($bodybgcolor1).'&color2='.urlencode($bodybgcolor2).
'&width='.$width.') repeat-y '.$bodybgcolor2,
'Small' => $width > $small_trigger_width ? '' : 'Small', // to use in css class-names
));
foreach(array(
'upper_left'=>array('width'=>-$corner_radius,'height'=>$header_height,'border'=>0,'bgcolor'=>$headerbgcolor),
'upper_right'=>array('width'=>$corner_radius,'height'=>$header_height,'border'=>0,'bgcolor'=>$headerbgcolor),
'lower_left'=>array('width'=>-$corner_radius,'height'=>-$corner_radius,'border'=>$border,'color'=>$headerbgcolor,'bgcolor'=>$bodybgcolor1),
'lower_right'=>array('width'=>$corner_radius,'height'=>-$corner_radius,'border'=>$border,'color'=>$headerbgcolor,'bgcolor'=>$bodybgcolor2),
) as $name => $data)
{
$tpl->set_var($name.'_corner',$GLOBALS['phpgw_info']['server']['webserver_url'].
'/calendar/inc/round_corners.php?width='.$data['width'].'&height='.$data['height'].
'&bgcolor='.urlencode($data['bgcolor']).
(isset($data['color']) ? '&color='.urlencode($data['color']) : '').
(isset($data['border']) ? '&border='.urlencode($data['border']) : ''));
}
$tooltip = $tpl->fp('tooltip','event_tooltip');
$tpl->set_var('tooltip',$this->html->tooltip($tooltip,False,array('BorderWidth'=>0,'Padding'=>0)));
$html = $tpl->fp('out','event_widget');
$view_link = $GLOBALS['phpgw']->link('/index.php',array('menuaction'=>'calendar.uicalendar.view','cal_id'=>$event['id'],'date'=>$event['start']['full']));
return $indent.'
'."\n".
$html.$indent."
\n";
}
function add_nonempty($content,$label,$one_per_line=False)
{
if (is_array($content))
{
$content = implode($one_per_line ? ",\n" : ', ',$content);
}
if (!empty($content))
{
return ''.$label.':'.
($one_per_line ? ' ' : ' ').
nl2br($this->html->htmlspecialchars($content)).' ';
}
return '';
}
/**
* Calculates a brighter color for a given color
*
* @param $rgb string color as #rrggbb value
* @param $decr int value to add to each component, default 64
* @return string the brighter color
*/
function brighter($rgb,$decr=64)
{
if (!preg_match('/^#?([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/',$rgb,$components))
{
return '#ffffff';
}
$brighter = '#';
for ($i = 1; $i <=3; ++$i)
{
$val = hexdec($components[$i]) + $decr;
if ($val > 255) $val = 255;
$brighter .= sprintf('%02x',$val);
}
//echo "brighter($rgb=".print_r($components,True).")=$brighter\n";
return $brighter;
}
/**
* trys to figure out the inner window width from the browser and installs an onResize handler
*
* If no $_REQUEST[windowInnerWidth] is present, the pages get reloaded with some javascript, which sets
* the width in the URL. If a width could be determined, an onResize handler gets installed, which refreshes
* the page, with the new width set in the URL.
* If we are allowed to set cookies, we additionaly set a cookie with the width, to save the additonal reload.
* An onLoad handler checks if we operate with the correct width, or reloads the page if not.
*/
function establish_width()
{
if (!isset($_REQUEST['windowInnerWidth'])) // we neither have a cookie nor an url-var, get one ...
{
?>
common->phpgw_exit();
}
$width = (int) $_GET['windowInnerWidth'] ? $_GET['windowInnerWidth'] : $_COOKIE['windowInnerWidth'];
if ($GLOBALS['phpgw_info']['server']['usecookies'])
{
$GLOBALS['phpgw']->session->phpgw_setcookie('windowInnerWidth',$width);
}
if ($width)
{
$GLOBALS['phpgw_info']['flags']['java_script'] = '
';
if (!is_object($GLOBALS['phpgw']->js))
{
$GLOBALS['phpgw']->js = CreateObject('phpgwapi.javascript');
}
$GLOBALS['phpgw']->js->set_onresize('reload_inner_width();');
$GLOBALS['phpgw']->js->set_onload('if ('.$width.'!=(window.innerWidth ? window.innerWidth : document.body.offsetWidth)) reload_inner_width();');
}
else
{
$width = 1000; // default, if the browser does not report it
}
return $width - 250; // 180 for sidebox-menu, TODO: this need to come from the template
}
}