import "Turbine";
import "Turbine.Gameplay";
import "Turbine.UI";
import "Turbine.UI.Extensions";
import "Turbine.UI.Lotro";
--import "Turbine.Utils";
import "FrostyPlugins.Calendar.DropDownBox";
import "FrostyPlugins.Calendar.CheckBox";
import "FrostyPlugins.Calendar.Options";
-- Get reference to user configurable options (singleton)
--options = FrostyPlugins.Calendar.OptionsInstance();
--table.dump("options",self.options);
-- --------------------------------------------------------------
-- CalendarEntry is a simple container class that holds and tracks
-- information about an "entry" on the calendar
--
-- Ideally the date/timestamps on each entry would be stored in a
-- global standard (UTC) to easily share calendar entries
-- between people in different timezones
-- Unfortunately there doesn't appear to be a way to obtain the
-- current timezone from Turbine.Engine.
-- - GetLocale() does NOT return timezone
-- - so we'll have to save the timezone (TZ) as a calendar setting
-- though converting timestamps is non-trivial.
--
-- For now - save start/end timestamps as 'yyyy-mm-dd hh:mm:ss'
-- in 24 format so they can easily be sorted without converting
-- them to epoch (seconds since 1970-01-01 00:00:00)
-- --------------------------------------------------------------
CalendarEntry = class( Turbine.Object );
local InviteeStatus = {
INVITED = 1,
ACCEPTED = 2,
DECLINED = 3,
}
-- Only include colors that have good contrast to dark background of calendar
local EntryColors = {
"White",
"Orange",
"Blue",
"SkyBlue",
"LightBlue",
"Red",
"Pink",
"HotPink",
"Yellow",
"Green",
"LightGreen",
"Gray",
"LightGray",
"Cyan",
};
function CalendarEntry:Constructor()
Turbine.Object.Constructor( self );
-- True if entry is editable, false otherwise
--self.isEditable = true;
self.Start = nil; -- STRING: yyyy-mm-ddThh:mm:ssz -- the start of the event
self.End = nil; -- STRING: yyyy-mm-ddThh:mm:ssz -- the end of the event
self.isAllDay = false; -- true if the event is all day
--self.isReminderEnabled = false; -- true if a reminder for this event is enabled
self.Description = nil; -- one-line title of event
self.Details = nil; -- multi-line details about event
-- Color to display for the event
-- - must save as colorName, rather than Color object
self.Color = "White";
-- A reminder
--self.Reminder = nil; -- If enabled, how many minutes before eventto display reminder pop-up
-- How to handle this if different character on same account sends update?
--self.Organizer = nil; -- who organized the event (if nil, then it is user event)
-- A map of others this event is shared with to their acceptance status
-- Invitees{person} = InviteeStatus
--self.Invitees = {};
end
-- --------------------------------------------------------------
-- CalendarEntryEditor is the editor window that allows the user
-- to change the time of the event or update it's description.
-- the user can also set an alarm / reminder that the time is
-- near.
--
-- ToDo (must wait for API updates)!
-- add a "notify" checkbox to let the user know 15 minutes before the event time
-- add an "alarm" button to alert the user audibly when the event time has been reached
-- AM vs PM? right now, it is a 24 hour clock
--
-- --------------------------------------------------------------
CalendarEntryEditor = class( Turbine.UI.Lotro.Window);
-- --------------------------------------------------------------
-- Constructor
--
-- Description: this is where the window is laid out, the fields
-- and buttons are created, and events are trapped.
-- --------------------------------------------------------------
function CalendarEntryEditor:Constructor()
--Turbine.Shell.WriteLine("CalendarEntryEditor:Constructor()");
Turbine.UI.Lotro.Window.Constructor( self );
-- load the last settings saved (we will use the position to locate the editor)
self:LoadSettings();
-- --------------------------------------------
-- window layout
-- --------------------------------------------
local windowMargin = 20;
local controlMargin = 5;
-- set window properties
self:SetSize( 400, 400 ); -- width,height
self:SetBackColor( Turbine.UI.Color() );
self:SetPosition( self.settings.positionX, self.settings.positionY );
self:SetText( "Update Entry..." );
self:SetOpacity( 1 );
self:SetAllowDrop( false );
-- create the StatusBar label at bottom of window
self.statusBarLabel = Turbine.UI.Label();
self.statusBarLabel:SetParent( self );
self.statusBarLabel:SetSize( self:GetWidth()-60, 20 ); -- width,height
self.statusBarLabel:SetPosition( -- left,top
30,
self:GetHeight() - self.statusBarLabel:GetHeight() - 5 );
--self.statusBarLabel:SetBackColor(Turbine.UI.Color.DimGray);
self.statusBarLabel:SetMultiline( false );
self.statusBarLabel:SetSelectable( false );
self.statusBarLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
--self.statusBarLabel:SetText( "<Status>" );
self.statusBarLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
self.statusBarLabel:SetVisible( true );
-- create the date start label
self.dateStartLabel = Turbine.UI.Label();
self.dateStartLabel:SetParent( self );
self.dateStartLabel:SetPosition( windowMargin, 40 ); -- left,top
self.dateStartLabel:SetSize( 40, 20 ); -- width,height
--self.dateStartLabel:SetBackColor(Turbine.UI.Color.DimGray);
self.dateStartLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.dateStartLabel:SetMultiline( false );
self.dateStartLabel:SetSelectable( false );
self.dateStartLabel:SetText( "Start:" );
self.dateStartLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleRight );
self.dateStartLabel:SetVisible( true );
-- create the date start textbox
self.dateStartText = Turbine.UI.TextBox();
self.dateStartText:SetParent( self );
self.dateStartText:SetPosition( -- left,top
self.dateStartLabel:GetLeft() + self.dateStartLabel:GetWidth() + controlMargin,
self.dateStartLabel:GetTop() );
self.dateStartText:SetSize( -- width,height
100,
self.dateStartLabel:GetHeight() );
self.dateStartText:SetBackColor(Turbine.UI.Color.DimGray);
self.dateStartText:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.dateStartText:SetMultiline( false );
self.dateStartText:SetSelectable( true );
self.dateStartText:SetText( "yyyy-mm-dd" );
self.dateStartText:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
self.dateStartText:SetVisible( true );
self.dateStartText.FocusLost = function( sender, args )
--Turbine.Shell.WriteLine("dateStartText:FocusLost");
self:isValid(); -- validate if entry can be saved
end
-- Unfortunately, the validating() method not available in the LOTRO API
-- Therefore, it is better to constrain user input so it is not possible
-- to enter invalid input in the first place. (e.g. use pick lists, etc.)
--self.dateStartText.Validating = function( sender, args )
-- Turbine.Shell.WriteLine("dateStartText:Validating");
--end
-- create the time start textbox
self.timeStartText = Turbine.UI.TextBox();
self.timeStartText:SetParent( self );
self.timeStartText:SetPosition( -- left,top
self.dateStartText:GetLeft() + self.dateStartText:GetWidth() + controlMargin,
self.dateStartLabel:GetTop() );
self.timeStartText:SetSize( -- width,height
60,
self.dateStartLabel:GetHeight() );
self.timeStartText:SetBackColor(Turbine.UI.Color.DimGray);
self.timeStartText:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.timeStartText:SetMultiline( false );
self.timeStartText:SetSelectable( true );
self.timeStartText:SetText( "hh:mm" );
self.timeStartText:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
self.timeStartText:SetVisible( true );
self.timeStartText.FocusLost = function( sender, args )
--Turbine.Shell.WriteLine("timeStartText:FocusLost");
self:isValid(); -- validate if entry can be saved
end
self.timeStartText.EnabledChanged = function( sender, args )
local isEnabled = self.timeStartText:IsEnabled();
--Turbine.Shell.WriteLine("timeStartText:enabledChanged [" .. tostring(isEnabled) .. "]");
--self.timeStartText:SetVisible(isEnabled);
if( isEnabled ) then
self.timeStartText:SetBackColor(Turbine.UI.Color.DimGray);
else
self.timeStartText:SetBackColor(Turbine.UI.Color.DarkSlateGray);
end
end
-- create the date end label
self.dateEndLabel = Turbine.UI.Label();
self.dateEndLabel:SetParent( self );
self.dateEndLabel:SetPosition( -- left,top
self.dateStartLabel:GetLeft(),
self.dateStartLabel:GetTop() + self.dateStartLabel:GetHeight() + 5 );
self.dateEndLabel:SetSize( self.dateStartLabel:GetSize() ); -- width,height
--self.dateEndLabel:SetBackColor(Turbine.UI.Color.DimGray);
self.dateEndLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.dateEndLabel:SetMultiline( false );
self.dateEndLabel:SetSelectable( false );
self.dateEndLabel:SetText( "End:" );
self.dateEndLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleRight );
self.dateEndLabel:SetVisible( true );
-- create the date end textbox
self.dateEndText = Turbine.UI.TextBox();
self.dateEndText:SetParent( self );
self.dateEndText:SetPosition( -- left,top
self.dateStartText:GetLeft(),
self.dateEndLabel:GetTop() );
self.dateEndText:SetSize( self.dateStartText:GetSize() ); -- width,height
self.dateEndText:SetBackColor(Turbine.UI.Color.DimGray);
self.dateEndText:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.dateEndText:SetMultiline( false );
self.dateEndText:SetSelectable( true );
self.dateEndText:SetText( "yyyy-mm-dd" );
self.dateEndText:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
self.dateEndText:SetVisible( true );
self.dateEndText.FocusLost = function( sender, args )
--Turbine.Shell.WriteLine("dateEndText:FocusLost");
self:isValid(); -- validate if entry can be saved
end
-- create the time end textbox
self.timeEndText = Turbine.UI.TextBox();
self.timeEndText:SetParent( self );
self.timeEndText:SetPosition( -- left,top
self.dateEndText:GetLeft() + self.dateEndText:GetWidth() + 5,
self.dateEndText:GetTop() );
self.timeEndText:SetSize( self.timeStartText:GetSize() ); -- width,height
self.timeEndText:SetBackColor(Turbine.UI.Color.DimGray);
self.timeEndText:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.timeEndText:SetMultiline( false );
self.timeEndText:SetEnabled( true );
self.timeEndText:SetSelectable( false );
self.timeEndText:SetText( "hh:mm" );
self.timeEndText:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
self.timeEndText:SetVisible( true );
self.timeEndText.FocusLost = function( sender, args )
--Turbine.Shell.WriteLine("timeEndText:FocusLost");
self:isValid(); -- validate if entry can be saved
end
self.timeEndText.EnabledChanged = function( sender, args )
local isEnabled = self.timeEndText:IsEnabled();
--Turbine.Shell.WriteLine("timeEndText:enabledChanged [" .. tostring(isEnabled) .. "]");
--self.timeEndText:SetVisible(isEnabled);
if( isEnabled ) then
self.timeEndText:SetBackColor(Turbine.UI.Color.DimGray);
else
self.timeEndText:SetBackColor(Turbine.UI.Color.DarkSlateGray);
end
end
-- create the allDay checkbox
-- - HACK! Seems to be a bug in Lotro.Checkbox not notifying CheckChanged
-- So use own control to workaround problem
--self.allDayCheckbox = Turbine.UI.Lotro.CheckBox();
--self.allDayCheckbox = Turbine.UI.CheckBox();
self.allDayCheckbox = FrostyPlugins.Calendar.CheckBox();
self.allDayCheckbox:SetParent( self );
self.allDayCheckbox:SetPosition( -- left,top
self.timeStartText:GetLeft() + self.timeStartText:GetWidth() + 5,
self.timeStartText:GetTop() );
self.allDayCheckbox:SetSize( 80, 20 ); -- width,height
self.allDayCheckbox:SetBackColor(Turbine.UI.Color.DimGray);
self.allDayCheckbox:SetOutlineColor( Turbine.UI.Color.Yellow );
self.allDayCheckbox:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.allDayCheckbox:SetVisible( true );
--self.allDayCheckbox:SetEnabled( true );
self.allDayCheckbox:SetChecked( false );
--self.allDayCheckbox:SetSelectable( true );
--self.allDayCheckbox:SetMouseVisible( true );
--self.allDayCheckbox:SetWantsUpdates( true );
self.allDayCheckbox:SetText( "All Day" ); -- put text in label
--self.allDayCheckbox:SetText( "" ); -- put text in label
self.allDayCheckbox.CheckChanged = function( sender, args )
local isChecked = self.allDayCheckbox:IsChecked();
--Turbine.Shell.WriteLine("allDayCheckbox:CheckChanged [" .. tostring(isChecked) .. "]");
self.timeStartText:SetEnabled( not isChecked );
self.timeEndText:SetEnabled( not isChecked );
end
-- CAUTION: Do NOT override the MouseClick or it will
-- interfere with the control processing Click events.
self.allDayCheckbox.MouseEnter = function( sender, args )
sender:SetFontStyle( Turbine.UI.FontStyle.Outline );
sender:SetVisible( false );
sender:SetVisible( true );
end
self.allDayCheckbox.MouseLeave = function( sender, args )
sender:SetFontStyle( Turbine.UI.FontStyle.None );
sender:SetVisible( false );
sender:SetVisible( true );
end
-- create the date field
--self.dateLabel = Turbine.UI.Label();
--self.dateLabel:SetParent( self );
--self.dateLabel:SetPosition( -- left,top
-- self.dateEndLabel:GetLeft(),
-- self.dateEndLabel:GetTop() + self.dateEndLabel:GetHeight() + 5 );
--self.dateLabel:SetSize( 180, 20 ); -- width,height
--self.dateLabel:SetBackColor(Turbine.UI.Color.DimGray);
--self.dateLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
--self.dateLabel:SetMultiline( false );
--self.dateLabel:SetText( "Date:" );
--self.dateLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleLeft );
--self.dateLabel:SetVisible( true );
--self.dateLabel:SetSelectable( false );
--self.dateLabel:SetMouseVisible( true );
--self.dateLabel:SetWantsUpdates( true );
-- create the time field
--self.timeLabel = Turbine.UI.Label();
--self.timeLabel:SetParent( self );
--self.timeLabel:SetPosition( -- left,top
-- self.dateLabel:GetLeft() + self.dateLabel:GetWidth() + 5,
-- self.dateLabel:GetTop() );
--self.timeLabel:SetSize( -- width,height
-- 40,
-- self.dateLabel:GetHeight() );
--self.timeLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
--self.timeLabel:SetMultiline( false );
--self.timeLabel:SetSelectable( false );
--self.timeLabel:SetText( "Time: " );
--self.timeLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleLeft );
--self.timeLabel:SetVisible( true );
--
--self.hoursUp = Turbine.UI.Button();
--self.hoursUp:SetParent( self );
--self.hoursUp:SetPosition( -- left,top
-- 230,
-- self.timeLabel:GetTop()-10 );
--self.hoursUp:SetSize( 20, 20 ); -- width,height
--self.hoursUp:SetBackground( "FrostyPlugins/Calendar/Resources/UpArrow.tga" );
--self.hoursUp:SetBlendMode( Turbine.UI.BlendMode.Overlay );
--self.hoursUp:SetVisible( true );
--
--self.hoursUp.MouseEnter = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/UpArrowHighlight.tga" );
-- self.hoursField:SetForeColor( Turbine.UI.Color( 1, 1, 0 ) );
--end
--self.hoursUp.MouseLeave = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/UpArrow.tga" );
-- self.hoursField:SetForeColor( Turbine.UI.Color( 1, 1, 1 ) );
--end
--
--self.hoursUp.Click = function( sender, args )
-- self:AdjustHours( 1 );
--end
--
--self.hoursDown = Turbine.UI.Button();
--self.hoursDown:SetParent( self );
--self.hoursDown:SetPosition( -- left,top
-- self.hoursUp:GetLeft(),
-- self.hoursUp:GetTop() + self.hoursUp:GetHeight() );
--self.hoursDown:SetSize( -- width,height
-- self.hoursUp:GetWidth(),
-- self.hoursUp:GetHeight() );
--self.hoursDown:SetBackground( "FrostyPlugins/Calendar/Resources/DownArrow.tga" );
--self.hoursDown:SetBlendMode( Turbine.UI.BlendMode.Overlay );
--self.hoursDown:SetVisible( true );
--
--self.hoursDown.MouseEnter = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/DownArrowHighlight.tga" );
-- self.hoursField:SetForeColor( Turbine.UI.Color( 1, 1, 0 ) );
--end
--self.hoursDown.MouseLeave = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/DownArrow.tga" );
-- self.hoursField:SetForeColor( Turbine.UI.Color( 1, 1, 1 ) );
--end
--
--self.hoursDown.Click = function( sender, args )
-- self:AdjustHours( -1 );
--end
--
--self.hoursField = Turbine.UI.Label();
--self.hoursField:SetParent( self );
--self.hoursField:SetPosition( 255, self.dateLabel:GetTop() ); -- left,top
--self.hoursField:SetSize( 20, self.dateLabel:GetHeight() ); -- width,height
--self.hoursField:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
--self.hoursField:SetMultiline( false );
--self.hoursField:SetSelectable( false );
--self.hoursField:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
--self.hoursField:SetVisible( true );
--
--self.colonField = Turbine.UI.Label();
--self.colonField:SetParent( self );
--self.colonField:SetPosition( 275, self.dateLabel:GetTop() ); -- left,top
--self.colonField:SetSize( 5, self.dateLabel:GetHeight() ); -- width,height
--self.colonField:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
--self.colonField:SetMultiline( false );
--self.colonField:SetSelectable( false );
--self.colonField:SetText( ":" );
--self.colonField:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
--self.colonField:SetVisible( true );
--
--self.minutesField = Turbine.UI.Label();
--self.minutesField:SetParent( self );
--self.minutesField:SetPosition( 280, self.dateLabel:GetTop() ); -- left,top
--self.minutesField:SetSize( 20, self.dateLabel:GetHeight() ); -- width,height
--self.minutesField:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
--self.minutesField:SetMultiline( false );
--self.minutesField:SetSelectable( false );
--self.minutesField:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
--self.minutesField:SetVisible( true );
--
--self.minutesUp = Turbine.UI.Button();
--self.minutesUp:SetParent( self );
--self.minutesUp:SetPosition( -- left,top
-- 300,
-- self.hoursUp:GetTop() );
--self.minutesUp:SetSize( -- width,height
-- self.hoursUp:GetWidth(),
-- self.hoursUp:GetHeight() );
--self.minutesUp:SetBackground( "FrostyPlugins/Calendar/Resources/UpArrow.tga" );
--self.minutesUp:SetBlendMode( Turbine.UI.BlendMode.Overlay );
--self.minutesUp:SetVisible( true );
--
--self.minutesUp.MouseEnter = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/UpArrowHighlight.tga" );
-- self.minutesField:SetForeColor( Turbine.UI.Color( 1, 1, 0 ) );
--end
--self.minutesUp.MouseLeave = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/UpArrow.tga" );
-- self.minutesField:SetForeColor( Turbine.UI.Color( 1, 1, 1 ) );
--end
--
--self.minutesUp.Click = function( sender, args )
-- self:AdjustMinutes( 1 );
--end
--
--self.minutesDown = Turbine.UI.Button();
--self.minutesDown:SetParent( self );
--self.minutesDown:SetPosition( -- left,top
-- 300,
-- self.hoursUp:GetTop() + self.hoursUp:GetHeight() );
--self.minutesDown:SetSize( -- width,height
-- self.hoursUp:GetWidth(),
-- self.hoursUp:GetHeight() );
--self.minutesDown:SetBackground( "FrostyPlugins/Calendar/Resources/DownArrow.tga" );
--self.minutesDown:SetBlendMode( Turbine.UI.BlendMode.Overlay );
--self.minutesDown:SetVisible( true );
--
--self.minutesDown.MouseEnter = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/DownArrowHighlight.tga" );
-- self.minutesField:SetForeColor( Turbine.UI.Color( 1, 1, 0 ) );
--end
--self.minutesDown.MouseLeave = function( sender, args )
-- sender:SetBackground( "FrostyPlugins/Calendar/Resources/DownArrow.tga" );
-- self.minutesField:SetForeColor( Turbine.UI.Color( 1, 1, 1 ) );
--end
--
--self.minutesDown.Click = function( sender, args )
-- self:AdjustMinutes( -1 );
--end
-- fixme: frosty
-- alarm button?
-- notify button?
self.buttonEntryColor = FrostyPlugins.Calendar.DropDownBox{itemList=EntryColors};
self.buttonEntryColor:SetParent( self );
self.buttonEntryColor:SetPosition( -- left,top
self.allDayCheckbox:GetLeft(),
self.dateEndLabel:GetTop() );
self.buttonEntryColor:SetSize( -- width,height
self.allDayCheckbox:GetWidth(),
self.dateEndLabel:GetHeight() );
self.buttonEntryColor:SetText( "Color" );
self.buttonEntryColor:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
--self.buttonEntryColor:SetBackColor(Turbine.UI.Color.Gray);
self.buttonEntryColor.SelectionChanged = function( sender, args )
local idx = self.buttonEntryColor:GetSelectedIndex();
local colorName = self.buttonEntryColor:GetSelectedValue();
--Turbine.Shell.WriteLine( string.format(
-- "buttonEntryColor.SelectionChanged: [%d] = [%s]",
-- idx, colorName) );
--self.buttonEntryColor:SetBackColor(Turbine.UI.Color[color]);
self.buttonEntryColor:SetForeColor( Turbine.UI.Color[colorName] );
self.Color = colorName;
end
-- create the Description label and field
self.descriptionLabel = Turbine.UI.Label();
self.descriptionLabel:SetParent( self );
self.descriptionLabel:SetPosition( -- left,top
self.dateEndLabel:GetLeft(),
self.dateEndLabel:GetTop() + self.dateEndLabel:GetHeight() + windowMargin );
self.descriptionLabel:SetSize( -- width,height
self:GetWidth() - windowMargin*2,
self.dateEndLabel:GetHeight() );
self.descriptionLabel:SetMultiline( false );
self.descriptionLabel:SetSelectable( false );
self.descriptionLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.descriptionLabel:SetText( "Description:" );
self.descriptionLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleLeft );
self.descriptionLabel:SetVisible( true );
self.descriptionField = Turbine.UI.Lotro.TextBox();
self.descriptionField:SetParent( self );
self.descriptionField:SetPosition( -- left,top
--self.dateLabel:GetLeft(),
self.dateEndLabel:GetLeft(),
self.descriptionLabel:GetTop() + self.descriptionLabel:GetHeight() );
self.descriptionField:SetSize( -- width,height
self:GetWidth() - windowMargin*2,
self.descriptionLabel:GetHeight() );
self.descriptionField:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.descriptionField:SetText( "Description stuff:" );
self.descriptionField:SetMultiline( false );
self.descriptionField:SetSelectable( true );
self.descriptionField:SetTextAlignment( Turbine.UI.ContentAlignment.TopLeft );
self.descriptionField:SetVisible( true );
self.descriptionField.FocusLost = function( sender, args )
--Turbine.Shell.WriteLine("descriptionField:FocusLost");
self:isValid(); -- validate if entry can be saved
end
-- create the Details label and field
self.detailsLabel = Turbine.UI.Label();
self.detailsLabel:SetParent( self );
self.detailsLabel:SetPosition( -- left,top
self.descriptionLabel:GetLeft(),
self.descriptionField:GetTop() + self.descriptionField:GetHeight() + windowMargin );
self.detailsLabel:SetSize( self.descriptionLabel:GetSize() ); -- width,height
self.detailsLabel:SetMultiline( false );
self.detailsLabel:SetSelectable( false );
self.detailsLabel:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.detailsLabel:SetText( "Details:" );
self.detailsLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleLeft );
self.detailsLabel:SetVisible( true );
self.detailsField = Turbine.UI.Lotro.TextBox();
self.detailsField:SetParent( self );
self.detailsField:SetPosition( -- left,top
self.detailsLabel:GetLeft(),
self.detailsLabel:GetTop() + self.detailsLabel:GetHeight() );
self.detailsField:SetSize( -- width,height
self.descriptionField:GetWidth(),
120 );
self.detailsField:SetFont( Turbine.UI.Lotro.Font.Verdana16 );
self.detailsField:SetMultiline( true );
self.detailsField:SetSelectable( true );
self.detailsField:SetTextAlignment( Turbine.UI.ContentAlignment.TopLeft );
self.detailsField:SetVisible( true );
self.detailsField.FocusLost = function( sender, args )
--Turbine.Shell.WriteLine("detailsField:FocusLost");
self:isValid(); -- validate if entry can be saved
end
-- create the save button
self.buttonSave = Turbine.UI.Lotro.Button();
self.buttonSave:SetParent( self );
self.buttonSave:SetPosition( -- left,top
40,
self.detailsField:GetTop() + self.detailsField:GetHeight() + windowMargin );
self.buttonSave:SetSize( 80, 25 ); -- width,height
self.buttonSave:SetText( "Save" );
self.buttonSave:SetVisible( true );
self.buttonSave:SetEnabled( false ); -- only enable if description provided
self.buttonSave.Click = function( sender, args )
self:Save();
end
-- create the Delete button
self.buttonDelete = Turbine.UI.Lotro.Button();
self.buttonDelete:SetParent( self );
self.buttonDelete:SetPosition( -- left,top
195,
self.buttonSave:GetTop() );
--self.buttonClear:SetSize( 80, 25 ); -- width,height
self.buttonDelete:SetSize( self.buttonSave:GetSize() ); -- width,height
self.buttonDelete:SetText( "Delete" );
self.buttonDelete:SetVisible( true );
self.buttonDelete.Click = function( sender, args )
self:Delete();
end
-- create the cancel button
self.buttonCancel = Turbine.UI.Lotro.Button();
self.buttonCancel:SetParent( self );
self.buttonCancel:SetPosition( -- left,top
280,
self.buttonSave:GetTop() );
--self.buttonCancel:SetSize( 80, 25 );
self.buttonCancel:SetSize( self.buttonSave:GetSize() ); -- width,height
self.buttonCancel:SetText( "Cancel" );
self.buttonCancel:SetVisible( true );
self.buttonCancel.Click = function( sender, args )
--Turbine.Shell.WriteLine("buttonCancel.Click");
self:Cancel();
end
-- make sure we listen for key presses
self:SetWantsKeyEvents( true );
-- --------------------------------------------
-- event handling
-- --------------------------------------------
--self.descriptionField.TextChanged = function( sender, args )
-- -- Check if description is blank
-- local description = self.descriptionField:GetText();
-- local hasDescription = ( string.len(description) > 0 );
-- -- Enable 'save' button if description provided
-- self.buttonSave:SetEnabled( hasDescription );
--end
--
-- if the escape key is pressed, assume it is a "cancel"
--
self.KeyDown = function( sender, args )
if( Turbine.UI.Lotro.Action.Escape == args.Action ) then
sender:Cancel();
end
end
--
-- if the position changes, save the new window location
--
self.PositionChanged = function( sender, args )
local x, y = self:GetPosition();
self.settings.positionX = x;
self.settings.positionY = y;
self:SaveSettings();
end
end
-- --------------------------------------------------------------
-- AdjustHours
--
-- Description: the user has pressed one of the hours buttons
-- (up or down). This function is used to bounds check the number
-- of hours and update the displayed hours field.
--
-- Params:
-- delta - integer - the amount of time to change the hours by.
-- this will be 1 or -1 hours
-- --------------------------------------------------------------
function CalendarEntryEditor:AdjustHours( delta )
self.hours = self.hours + delta;
if( self.hours < 0 ) then
self.hours = 23;
end
if( self.hours > 23 ) then
self.hours = 0;
end
local newHoursLabel = tostring( self.hours );
if( self.hours < 10 ) then
newHoursLabel = "0" .. self.hours;
end
self.hoursField:SetText( newHoursLabel );
end
-- --------------------------------------------------------------
-- AdjustMinutes
--
-- Description: the user has pressed one of the minutes buttons
-- (up or down). This function is used to bounds check the number
-- of minutes and update the displayed minutes field.
--
-- Params:
-- delta - integer - the amount of time to change the minues by.
-- this will be 1 or -1 minutes
-- --------------------------------------------------------------
function CalendarEntryEditor:AdjustMinutes( delta )
self.minutes = self.minutes + delta;
if( self.minutes < 0 ) then
self.minutes = 59;
end
if( self.minutes > 59 ) then
self.minutes = 0;
end
local newMinutesLabel = tostring( self.minutes );
if( self.minutes < 10 ) then
newMinutesLabel = "0" .. self.minutes;
end
self.minutesField:SetText( newMinutesLabel );
end
--------------------------------------------------------------------------
--- isValid
--
-- Description: Check if the user supplied data is valid
-- @return true if valid, false otherwise
-- --------------------------------------------------------------
function CalendarEntryEditor:isValid()
local strStartDate = string.format("%sT%s:00",
self.dateStartText:GetText(),
self.timeStartText:GetText() );
--Turbine.Shell.WriteLine(string.format("isValid strStartDate = [%s]",strStartDate));
local status,err = pcall( DateTime.parse, DateTime, strStartDate);
if( not status ) then
local msg = string.format("Start Date is invalid: %s",err);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
--self.statusBarLabel:SetBackColor(Turbine.UI.Color.DimGray);
self.dateStartText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
local now = DateTime:now();
local minYear = now.Year - Options.yearlimit;
local maxYear = now.Year + Options.yearlimit;
local startDate = DateTime:parse(strStartDate);
if( startDate.Year > maxYear ) then
local msg = string.format("Start year must be less than [%d]",maxYear);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
if( startDate.Year < minYear ) then
local msg = string.format("Start year must be more than [%d]",minYear);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
--Turbine.Shell.WriteLine("dateStartText is ok");
self.dateStartText:SetBackColor(Turbine.UI.Color.DimGray);
local strEndDate = string.format("%sT%s:00",
self.dateEndText:GetText(),
self.timeEndText:GetText() );
--Turbine.Shell.WriteLine(string.format("isValid strEndDate = [%s]",strEndDate));
local status,err = pcall( DateTime.parse, DateTime, strEndDate);
if( not status ) then
local msg = string.format("End Date is invalid: %s",err);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
-- Verify end date is AFTER start date
local endDate = DateTime:parse(strEndDate);
if( startDate > endDate ) then
local msg = "endDate must be after startDate";
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
if( endDate.Year > maxYear ) then
local msg = string.format("End year must be less than [%d]",maxYear);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
if( endDate.Year < minYear ) then
local msg = string.format("End year must be more than [%d]",minYear);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
local duration = endDate:DaysSince(startDate);
if( duration > Options.maxEventDurationAllDays ) then
local msg = string.format(
"All Day events must be shorter than %d days",
Options.maxEventDurationAllDays);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
if( not self.allDayCheckbox:IsChecked() and
(duration > Options.maxEventDurationPartialDays) ) then
local msg = string.format(
"Partial day events be shorter than %d days",
Options.maxEventDurationPartialDays);
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
-- Verify duration of event is not too long
self.dateEndText:SetBackColor(Turbine.UI.Color.DimGray);
-- Verify description provided
if( string.len(self.descriptionField:GetText()) > 0 ) then
self.descriptionField:SetBackColor(Turbine.UI.Color.Black);
else
local msg = "Missing description!";
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Red);
self.descriptionField:SetBackColor(Turbine.UI.Color.Red);
self.buttonSave:SetEnabled( false );
return false;
end
-- If it is a read-only entry (e.g. Global Event)
-- then don't allow it to be saved/changed
local isReadOnly = (nil ~= self.calendarEntry.ReadOnly) and
self.calendarEntry.ReadOnly;
self.buttonDelete:SetEnabled(not isReadOnly);
self.buttonSave:SetEnabled(not isReadOnly);
if( isReadOnly ) then
local msg = "Entry is read only";
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Yellow);
return false;
end
-- If you made it this far, it is valid
-- so enable 'save' button
self.buttonSave:SetEnabled( true );
if( endDate < now ) then
local msg = "End date is in the past";
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Yellow);
--self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
--self.buttonSave:SetEnabled( false );
return true; -- just a warning
end
if( startDate < now ) then
local msg = "Start date is in the past";
self.statusBarLabel:SetText(msg);
self.statusBarLabel:SetForeColor(Turbine.UI.Color.Yellow);
--self.dateEndText:SetBackColor(Turbine.UI.Color.Red);
--self.buttonSave:SetEnabled( false );
return true; -- just a warning
end
self.statusBarLabel:SetForeColor(Turbine.UI.Color.DimGray);
self.statusBarLabel:SetText("Entry is valid");
return true;
end
--------------------------------------------------------------------------
--- Save
--
-- Description: the user has pressed the "Save" button. Notify
-- the calendar that the enclosed CalendarEntry should be saved.
-- --------------------------------------------------------------
function CalendarEntryEditor:Save()
local calendarEntry = self.calendarEntry;
Turbine.Shell.WriteLine("CalendarEntryEditor:Save " .. tostring(calendarEntry));
-- Do *NOT* update the dateEntry field
-- - the calenderWindow will use to to find the old entry in case
-- the user changed the start date
-- - the calender window update this field prior to saving it
-- update the entry with data from the window controls
calendarEntry.Start = string.format("%sT%s:00",
self.dateStartText:GetText(),
self.timeStartText:GetText());
calendarEntry.End = string.format("%sT%s:00",
self.dateEndText:GetText(),
self.timeEndText:GetText());
calendarEntry.isAllDay = self.allDayCheckbox:IsChecked();
--self.isReminderEnabled = self.reminderCheckbox:IsChecked();
calendarEntry.Description = self.descriptionField:GetText();
calendarEntry.Details = self.detailsField:GetText();
calendarEntry.Color = self.Color;
--table.dump("calendarEntry",calendarEntry);
-- save the settings - notify the creator that the data is ready
if( self.notifyCalendar ) then
self.notifyCalendar:NotifySaveEntry( calendarEntry );
end
self:SetVisible( false ); -- hide editor window
end
-- --------------------------------------------------------------
-- Cancel
--
-- Description: the user has pressed the "Cancel" button. There
-- is nothing to do but hide the window.
-- --------------------------------------------------------------
function CalendarEntryEditor:Cancel()
--Turbine.Shell.WriteLine("CalendarEntryEditor:Cancel");
-- turn ourselves invisible, nothing else to do
self:SetVisible( false );
end
-- --------------------------------------------------------------
--- Clear
--
-- Description: the user has pressed the "Delete" button.
-- Notify the calendar that the enclosed CalendarEntry should be cleared.
-- --------------------------------------------------------------
function CalendarEntryEditor:Delete()
--Turbine.Shell.WriteLine("CalendarEntryEditor:Delete");
-- TODO - prompt "Are you sure?"
-- notify the creator that the data should be deleted
if( self.notifyCalendar ) then
self.notifyCalendar:NotifyDeleteEntry( self );
end
self:SetVisible( false );
end
-- --------------------------------------------------------------
--- InitializeEntry
--
-- Description: the entry is used to populate the fields on the editor.
-- If the user hits Save or Clear the input calendar is used to notify
-- of data changes.
--
-- @param entry - a CalendarEntry passed in from the calendar
-- @param calendar - the CalendarWindow that owns this object
-- --------------------------------------------------------------
function CalendarEntryEditor:InitializeEntry( entry, calendar )
--Turbine.Shell.WriteLine( "CalendarEntryEditor:InitializeEntry(" .. tostring(entry) .. ")" );
self.notifyCalendar = calendar; -- who to notify
self.calendarEntry = entry; -- the entry to add/update
--table.dump("calendarEntry",entry);
self.allDayCheckbox:SetChecked( entry.isAllDay );
-- call this manually since it doesn't seem to happen on its own
self.allDayCheckbox:CheckChanged();
local dateEntry = entry.DateEntry;
--Turbine.Shell.WriteLine( " start=" .. entry.Start );
self:InitializeDateFields(
entry.Start,
self.dateStartText,
self.timeStartText );
--Turbine.Shell.WriteLine( " end=" .. entry.End );
self:InitializeDateFields(
entry.End,
self.dateEndText,
self.timeEndText );
if( "string" == type(entry.Color) ) then
self.Color = entry.Color;
else
self.Color = "White";
end
self.buttonEntryColor:SetSelectedValue(self.Color);
--if( not entry.Start ) then
-- entry.TimeEntry = "12:00";
-- Turbine.Shell.WriteLine( "entry.TimeEntry = [" .. entry.TimeEntry .. "]" );
--end
--if( not entry.DateStart ) then
-- entry.DateStart = CalTools:Date(today);
-- entry.DateStart.Minute = 0;
-- Turbine.Shell.WriteLine( "entry.DateStart = [" .. entry.DateStart:tostring() .. "]" );
--end
--if( not entry.DateEnd ) then
-- entry.DateEnd = CalTools:Date(today);
-- entry.DateStart.Hour = 24;
-- entry.DateStart.Minute = 0;
-- entry.isAllDay = true;
-- entry.Description = "Enter text here...";
-- Turbine.Shell.WriteLine( "entry.DateEnd = [" .. entry.DateEnd:tostring() .. "]" );
--end
-- the user has clicked on a date entry - populate our fields with the data
-- that they have specified and update the screen
-- note: it is assumed that the entry.DateEntry is 5 characters, and in
-- the format "12:59" or "03:45"
--if( string.len( entry.TimeEntry) ~= 5 ) then
-- self.hours = "12";
-- self.minutes = "59";
--else
-- self.hours = string.sub( entry.TimeEntry, 1, 2 );
-- self.minutes = string.sub( entry.TimeEntry, 4, 5 );
--end
-- I cheat here by adjusting the hours and minutes by "0", which will cause
-- them to redisplay using their new values
--self:AdjustHours( 0 );
--self:AdjustMinutes( 0 );
self.descriptionField:SetText( entry.Description );
--self.descriptionField:TextChanged(sender, args); -- force update
self.detailsField:SetText( entry.Details );
-- select all the text and make the field have focus
-- fixme: frosty
-- API does not yet support focus setting
-- * without focus, placing the cursor in the field
-- will remove the selection - boo!
-- self.descriptionField:SelectAll();
-- now show ourselves
self:SetVisible( true );
self:Activate( true ); -- bring window to front
self:isValid(); -- validate if entry can be saved
end
-- --------------------------------------------------------------
-- InitializeDateFields
--
-- Description: the entry is used to populate the fields on the editor.
-- If the user hits Save or Clear the input calendar is used to notify
-- of data changes.
--
-- @param szDate - the date in UTC zulu time
-- @param dateField - the date TextBox control to initialize
-- @param timeField - the time TextBox control to initialize
-- --------------------------------------------------------------
function CalendarEntryEditor:InitializeDateFields( szDate, dateField, timeField )
--Turbine.Shell.WriteLine( "CalendarEntryEditor:InitializeDateFields" ..
-- " str=[" .. szDate .. "]");
--local tmp = DateTime:parse("1988-12-20 23:45Z");
--Turbine.Shell.WriteLine( "CalendarEntryEditor:InitializeDateFields" ..
-- " tmp=[" .. tmp:tostring() .. "]");
local d = DateTime:parse(szDate);
if( not d ) then
Turbine.Shell.WriteLine( " Detected invalid date[" .. szDate .. "]");
d = DateTime:now();
end
dateField:SetText( d:ymd() );
timeField:SetText( d:time() );
end
-- --------------------------------------------------------------
-- LoadSettings
--
-- Description: loads our internal settings from disk. For this class,
-- this includes the position of the editor window. if the position does
-- not exist, we attempt to place it in the center of the window.
-- --------------------------------------------------------------
function CalendarEntryEditor:LoadSettings()
-- load the settings. If a value is not available, set a default value
self.settings = Turbine.PluginData.Load(
-- Turbine.DataScope.Character,
Turbine.DataScope.Account,
"CalendarEntrySettings" );
if ( type( self.settings ) ~= "table" ) then
self.settings = { };
end
-- load prior window position
if ( not self.settings.positionX ) then
self.settings.positionX = (Turbine.UI.Display.GetWidth() / 2) - (self:GetWidth() / 2 );
end
if ( not self.settings.positionY ) then
self.settings.positionY = (Turbine.UI.Display.GetHeight() / 2) - (self:GetHeight() / 2 );
end
end
-- --------------------------------------------------------------
-- SaveSettings
--
-- Description: save our internal settings to disk. For this class,
-- this includes the position of the editor window
-- --------------------------------------------------------------
function CalendarEntryEditor:SaveSettings()
-- save the settings
Turbine.PluginData.Save(
-- Turbine.DataScope.Character,
Turbine.DataScope.Account,
"CalendarEntrySettings",
self.settings );
end