lotrointerface.com
Search Downloads

LoTROInterface SVN Calendar

[/] [trunk/] [FrostyPlugins/] [Calendar/] [Orig_CalendarWindow.lua] - Rev 2

Compare with Previous | Blame | View Log

import "Turbine";
import "Turbine.Gameplay";
import "Turbine.UI";
import "Turbine.UI.Extensions";
import "Turbine.UI.Lotro";
import "Turbine.Utils";
import "FrostyPlugins.Calendar.CalendarEntry";

-- --------------------------------------------------------------
-- CalendarWindow is a display of the current month.  You can see
-- events that are on the calendar and edit them.
--
-- ToDo:
-- allow multiple events per day
-- add icons for events?
-- --------------------------------------------------------------

CalendarWindow = 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 CalendarWindow:Constructor()
        Turbine.UI.Lotro.Window.Constructor( self );

        -- load the last settings saved
        self:LoadSettings();

  -- statics
  self.monthLabels = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }
  self.monthsTable = { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
  self.monthsLeapTable = { 6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
  self.calendarEntryEditor = FrostyPlugins.Calendar.CalendarEntryEditor();
  self.calendarEntryEditor:SetVisible( false );
  
  -- --------------------------------------------
  -- window layout
  -- --------------------------------------------
  
        -- set window properties
        self:SetSize( 250, 280 );
        self:SetBackColor( Turbine.UI.Color() );
        self:SetPosition( self.settings.positionX, self.settings.positionY );
        self:SetText( "Calendar" );
        self:SetOpacity( 1 );
        self:SetAllowDrop( false );

  -- the layout will look something like:
  
  --  -         June          +
  -- 
  --      1   2   3   4   5   6
  --  7   8   9  10  11  12  13
  -- 14  15  16  17  18  19  20
  -- 21  22  23  24  25  26  27
  -- 28  29  30
  --

        -- create the month/year - button
        self.buttonLeft = Turbine.UI.Button();
        self.buttonLeft:SetBackground( "FrostyPlugins/Calendar/Resources/LeftArrow.tga" );
        self.buttonLeft:SetBlendMode( Turbine.UI.BlendMode.Overlay );
        self.buttonLeft:SetParent( self );
        self.buttonLeft:SetPosition( 20, 42 );
        self.buttonLeft:SetSize( 20, 20 );
        self.buttonLeft:SetVisible( true );

  self.buttonLeft.MouseEnter = function( sender, args )
          sender:SetBackground( "FrostyPlugins/Calendar/Resources/LeftArrowHighlight.tga" );
        end
  self.buttonLeft.MouseLeave = function( sender, args )
          sender:SetBackground( "FrostyPlugins/Calendar/Resources/LeftArrow.tga" );
        end
        
  self.buttonLeft.Click = function( sender, args )
                self:AdjustMonth( -1 );
        end
        
  -- create the month layout
  self.monthLabel = Turbine.UI.Label();
  self.monthLabel:SetFont( Turbine.UI.Lotro.Font.Verdana20 );
  self.monthLabel:SetParent( self );
        self.monthLabel:SetPosition( 45, 40 );
        self.monthLabel:SetMultiline( false );  
        self.monthLabel:SetSelectable( false ); 
        self.monthLabel:SetSize( 160, 25 );
        self.monthLabel:SetText( "September" );
        self.monthLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
        self.monthLabel:SetVisible( true );

        -- create the month/year + button
        self.buttonRight = Turbine.UI.Button();
        self.buttonRight:SetBackground( "FrostyPlugins/Calendar/Resources/RightArrow.tga" );
        self.buttonRight:SetBlendMode( Turbine.UI.BlendMode.Overlay );
        self.buttonRight:SetParent( self );
        self.buttonRight:SetPosition( 205, 42 );
        self.buttonRight:SetSize( 20, 20 );
        self.buttonRight:SetVisible( true );

  self.buttonRight.MouseEnter = function( sender, args )
          sender:SetBackground( "FrostyPlugins/Calendar/Resources/RightArrowHighlight.tga" );
        end
  self.buttonRight.MouseLeave = function( sender, args )
          sender:SetBackground( "FrostyPlugins/Calendar/Resources/RightArrow.tga" );
        end

  self.buttonRight.Click = function( sender, args )
                self:AdjustMonth( 1 );
        end

  -- create the actual calendar items
  self.gridElements = {};
  local index = 1;
  local rowCount = 6;
  local columnCount = 7;
        for i = 1, rowCount do
          for j = 1, columnCount do
            local gridElement = Turbine.UI.Button();
            local x = -10 + j * 30;
            local y = 40 + i * 30;
            
            gridElement:SetBackground( "FrostyPlugins/Calendar/Resources/DateBackground.jpg" );
            gridElement:SetBackColorBlendMode( Turbine.UI.BlendMode.Overlay );
            
      gridElement:SetFont( Turbine.UI.Lotro.Font.Verdana20 );
      gridElement:SetParent( self );
            gridElement:SetPosition( x, y );
            gridElement:SetMultiline( false );  
            gridElement:SetSelectable( false ); 
            gridElement:SetSize( 30, 30 );
            gridElement:SetText( "x" );     
            gridElement:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
            gridElement:SetVisible( true );
            
            gridElement.Click = function( sender, args )
              self:UpdateCalendarEntry( sender:GetText() );
            end
            
            gridElement.MouseEnter = function( sender, args )
              sender:SetForeColor( Turbine.UI.Color( 1, 1, 0 ) );
            end

            gridElement.MouseLeave = function( sender, args )
              sender:SetForeColor( Turbine.UI.Color( 1, 1, 1 ) );
            end

      self.gridElements[ index ] = gridElement;
      index = index + 1;
                end
        end

  -- the special "today" overlay
  self.todayOverlay = Turbine.UI.Window();
  self.todayOverlay:SetBackground( "FrostyPlugins/Calendar/Resources/TodayOverlay.tga" );
  self.todayOverlay:SetMouseVisible( false );
  self.todayOverlay:SetParent( self );
  self.todayOverlay:SetPosition( 0, 0 );
  self.todayOverlay:SetSize( 30, 30 );
  self.todayOverlay:SetVisible( false );

  -- the radio button for storing data on the character or the account
  self.dataLocationLabel = Turbine.UI.Label();
  self.dataLocationLabel:SetFont( Turbine.UI.Lotro.Font.Verdana14 );
  self.dataLocationLabel:SetMouseVisible( true );
  self.dataLocationLabel:SetOutlineColor( Turbine.UI.Color( 1, 1, 0 ) );
  self.dataLocationLabel:SetParent( self );
        self.dataLocationLabel:SetPosition( 20, 250 );
        self.dataLocationLabel:SetMultiline( false );   
        self.dataLocationLabel:SetSize( 210, 20 );
        self.dataLocationLabel:SetTextAlignment( Turbine.UI.ContentAlignment.MiddleCenter );
        self.dataLocationLabel:SetVisible( true );

  if( true == self.dataLocation.StoredOnCharacter ) then
    self.dataLocationLabel:SetText( "Save Data on Character" );
  else
    self.dataLocationLabel:SetText( "Save Data on Account" );
  end

  -- fixme: frosty
  --        there is a bug with SetFontStyle - it does not "dirty" the control.
  --        to get around this, toggle the visibility of the field
  self.dataLocationLabel.MouseEnter = function( sender, args )
          sender:SetFontStyle( Turbine.UI.FontStyle.Outline );
    self.dataLocationLabel:SetVisible( false );
    self.dataLocationLabel:SetVisible( true );
        end
  
  self.dataLocationLabel.MouseLeave = function( sender, args )
          sender:SetFontStyle( Turbine.UI.FontStyle.None );
    self.dataLocationLabel:SetVisible( false );
    self.dataLocationLabel:SetVisible( true );
        end
        
  self.dataLocationLabel.MouseClick = function( sender, args )
    self.dataLocation.StoredOnCharacter = not self.dataLocation.StoredOnCharacter;
    self:SaveSettings();
    if( true == self.dataLocation.StoredOnCharacter ) then
      self.dataLocationLabel:SetText( "Save Data on Character" );
    else
      self.dataLocationLabel:SetText( "Save Data on Account" );
    end
        end
  
  -- this is the label for the dataLocation store
  
        -- make sure we listen for key presses
        self:SetWantsKeyEvents( true );

  -- --------------------------------------------
  -- event handling
  -- --------------------------------------------
  
  --
  -- if the escape key is pressed, hide the window
  --
        self.KeyDown = function( sender, args )
                -- do this if the escape key is pressed
                if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
                        sender:SetVisible( false )
                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

  -- --------------------------------------------
  -- initialize the actual calendar
  -- --------------------------------------------
  self:InitializeCalendar();
  self:RebuildCalendar();
end

-- --------------------------------------------------------------
-- InitializeCalendar
--
-- Description: initialize the calendar: get the current day and
-- initialize the starting day and month
-- --------------------------------------------------------------
function CalendarWindow:InitializeCalendar()
  -- track "today"
  self.today = Turbine.Engine.GetDate();

  -- initialize the rest of the date members that we use to
  -- display the calendar
  self.currentMonth = self.today.Month;
  self.currentYear = self.today.Year;
end

-- --------------------------------------------------------------
-- AdjustMonth
--
-- Description: the user has pressed one of the month buttons
-- (inc. or dec.)  This function is used to bounds check the number
-- of months and rebuild the calendar
--
-- Params:
-- delta - integer - the amount of time to change the month by.
--                   this will be 1 or -1 months
-- --------------------------------------------------------------
function CalendarWindow:AdjustMonth( delta )
  -- if we're trying to go before 2000 or after 2099, forget it!
  self.currentMonth = self.currentMonth + delta;
  if( self.currentMonth < 1 ) then
    self.currentYear = self.currentYear - 1;
    self.currentMonth = 12;
    if( self.currentYear < 2000 ) then
      self.currentYear = 2000;
      self.currentMonth = 1;
    end
  end
  if( self.currentMonth > 12 ) then
    self.currentYear = self.currentYear + 1;
    self.currentMonth = 1;
    if( self.currentYear > 2099 ) then
      self.currentYear = 2099;
      self.currentMonth = 12;
    end
  end
  self:RebuildCalendar();
end

-- --------------------------------------------------------------
-- RebuildCalendar
--
-- Description: update the calendar window with any changes.  Changes
-- include: increasing or decreasing months (the entire calendar needs
-- to be redrawn), and saving or clearing events.
--
-- fixme: frosty
--        can I pass in a hint so that I don't have to rebuild the
--        entire calendar from scratch every time?  The current method
--        is overkill when saving or clearing the calendar events.
-- --------------------------------------------------------------
function CalendarWindow:RebuildCalendar()
  -- update the month label: month year
  local updateLabel = self.monthLabels[ self.currentMonth ] .. " " .. self.currentYear;
  self.monthLabel:SetText( updateLabel );

  -- determine the number of days in the month
  local bLeapYear = 0;
  local numberOfDays = 31;
  if( ( self.currentMonth == 4 ) or ( self.currentMonth == 6 ) or ( self.currentMonth == 9 ) or ( self.currentMonth == 11 ) ) then
    numberOfDays = 30;
  end
  if( self.currentMonth == 2 ) then
    if( ( 0 == ( self.currentYear % 4 ) ) and ( ( self.currentYear % 500 ) ~= 0 ) ) then
      numberOfDays = 29;
      bLeapYear = 1;
    else
      numberOfDays = 28;
    end
  end

  -- determine where to start updating the calendar
  -- anything in the 2000s is century "6"
  local centuriesTable = 6;
  
  -- take the digits from the current year and % 4 it
  local yearsTable = self.currentYear - ( ( self.currentYear % 100 ) * 100 );
  local yearsMod4 = yearsTable % 4;

  -- lookup the months from the month table
  local monthTable = self.monthsTable[ self.currentMonth ];
  if( bLeapYear ) then
    monthTable = self.monthsLeapTable[ self.currentMonth ];
  end
  
  -- add all the numbers, including the day the months starts, which is 1;
  local dayTotal = centuriesTable + yearsTable + yearsMod4 + monthTable + 1;

  -- dayTotal % 7 will give us the day of the week
  -- however, that day of the week is mod 6... we need to add '1' to work in our calendar
  local startDay = ( dayTotal % 7 ) + 1;
  
  -- create a key string for today
  local todayString = tostring( self.today.Day ) .. self.monthLabels[ self.today.Month ] .. self.today.Year;
  self.todayOverlay:SetVisible( false );
  
  -- update the calendar
  -- we update 42 items, since the calendar is 6 rows of 7 days
  local dayIndex = 1;
        for i = 1, 42 do
          -- reset any indicators that the date has an event on it
          self.gridElements[ i ]:SetBackColor( Turbine.UI.Color( 0, 0, 0, 0 ) );

    local newLabel = "";
          if( i > startDay ) then
            if( i < ( startDay + numberOfDays + 1 ) ) then
              local dayIndex = i - startDay;
              newLabel = tostring( dayIndex );
              
              -- if this date has an entry on it, change the back color!
              local entryKey = tostring( dayIndex ) .. self.monthLabels[ self.currentMonth ] .. self.currentYear;
        local calendarEntry = self.settings.CalendarEntryArray[ entryKey ];
        if( calendarEntry ) then
                self.gridElements[ i ]:SetBackColor( Turbine.UI.Color( .75, .5, .5, 0 ) );
              end
        
        -- if this day is today, then we move the "today" indicator and change its visibility
        if( entryKey == todayString ) then
          local x, y = self.gridElements[ i ]:GetPosition();
          self.todayOverlay:SetPosition( x, y );
          self.todayOverlay:SetVisible( true );
        end
            end
          end
          self.gridElements[ i ]:SetText( newLabel );
          
          -- we only show the last row when the month actually requires it
          -- (the 30th and/or 31st fall on a Sunday/Monday)
          if( i > 35 ) then
            if( startDay + numberOfDays > 35 ) then
              self.gridElements[ i ]:SetVisible( true );
            else
              self.gridElements[ i ]:SetVisible( false );
            end
          end
        end
end

-- --------------------------------------------------------------
-- UpdateCalendarEntry
--
-- Description: the user has clicked on a date in the calendar.
-- retrieve the existing entry (if it exists) and initialize the
-- CalendarEntryEditor with the entry.
--
-- Params:
-- dayString - string - the string-ified day, i.e. 12 becomes "12"
--
-- fixme: frosty
--        currently, the existing system only allows for a single
--        event per day.
-- --------------------------------------------------------------
function  CalendarWindow:UpdateCalendarEntry( dayString )
  -- create a string used to access the list of CalendarEntrys
  local entryKey = dayString .. self.monthLabels[ self.currentMonth ] .. self.currentYear;
  
  -- look this entry up in the table
  local calendarEntry = self.settings.CalendarEntryArray[ entryKey ];
  if( not calendarEntry ) then
    calendarEntry = FrostyPlugins.Calendar.CalendarEntry();
    calendarEntry.DateEntry = entryKey;
    calendarEntry.TimeEntry = "12:00";
    calendarEntry.Description = "Enter text here...";
  end

  -- display the window that edits the CalendarEntry
  -- the editor will take care of calling us back to save the entry
  self.calendarEntryEditor:InitializeEntry( calendarEntry, self );
end

-- --------------------------------------------------------------
-- NotifySaveEntry
--
-- Description: the user has modified an entry on the calendar and
-- elected to save it to disk. look up the entry to see if it is something
-- we know about.  if there is no current entry, create one.  update the
-- entry with the information on the editor and save the entry to disk.
-- finally, rebuild the calendar.
--
-- Params:
-- entryEditor - CalendarEntryEditor - the editor window that contains
--               the CalendarEntry that is being saved
-- --------------------------------------------------------------
function CalendarWindow:NotifySaveEntry( entryEditor )

  -- look this input entry's date and time up in the table
  local entryKey = entryEditor.calendarEntry.DateEntry;
  local calendarEntry = self.settings.CalendarEntryArray[ entryKey ];
  if( not calendarEntry ) then
    -- if not there, create one
    calendarEntry = FrostyPlugins.Calendar.CalendarEntry();
  end

  -- update the entry with the input data
  calendarEntry.DateEntry = entryEditor.calendarEntry.DateEntry;
  calendarEntry.TimeEntry = entryEditor.hoursField:GetText() .. ":" .. entryEditor.minutesField:GetText();
  calendarEntry.Description = entryEditor.descriptionField:GetText();
  
  -- and save it back to the calendar
  self.settings.CalendarEntryArray[ entryKey ] = calendarEntry;
  self:SaveSettings();
  self:RebuildCalendar();
end

-- --------------------------------------------------------------
-- NotifyClearEntry
--
-- Description: the user has cleared an entry from the calendar.
-- look up the entry to make sure it is something we know about.
-- if so, delete it from the list and rebuild the calendar.
--
-- Params:
-- entryEditor - CalendarEntryEditor - the editor window that contains
--               the CalendarEntry that is being cleared
-- --------------------------------------------------------------
function CalendarWindow:NotifyClearEntry( entryEditor )
  local entryKey = entryEditor.calendarEntry.DateEntry;
  local calendarEntry = self.settings.CalendarEntryArray[ entryKey ];
  if( calendarEntry ) then
    self.settings.CalendarEntryArray[ entryKey ] = nil;
    self:SaveSettings();
    self:RebuildCalendar();
  end
end

-- --------------------------------------------------------------
-- LoadSettings
--
-- Description: loads our internal settings from disk.  For this class,
-- this includes the position of the calendar window and the list of
-- events that have been created.  if the position does not exist, we
-- attempt to place it in the center of the window.  if the entry list
-- does not exist, we create it.
-- --------------------------------------------------------------
function CalendarWindow:LoadSettings()
  -- the first thing to check: where are we storing the settings for this
  -- user?  at the account level or the character level?  to do this, we
  -- read a special object that contains this information.
  self.dataLocation = Turbine.PluginData.Load( Turbine.DataScope.Character, "CalendarDataSettings" );
  if( type( self.dataLocation ) ~= "table" ) then
    self.dataLocation = { };
  end
  if( nil == self.dataLocation.StoredOnCharacter ) then
    self.dataLocation.StoredOnCharacter = true;
  end
  
        -- load the settings from either the character or the account scopt.
  if( true == self.dataLocation.StoredOnCharacter ) then
        self.settings = Turbine.PluginData.Load( Turbine.DataScope.Character, "CalendarWindowSettings" );
  else
        self.settings = Turbine.PluginData.Load( Turbine.DataScope.Account, "CalendarWindowSettings" );
  end

  -- If any of the values are not available, set a default value
        if ( type( self.settings ) ~= "table" ) then
                self.settings = { };
        end

        if ( nil == self.settings.positionX ) then
                self.settings.positionX = (Turbine.UI.Display.GetWidth() / 2) - (self:GetWidth() / 2 ); 
        end

        if ( nil == self.settings.positionY ) then
                self.settings.positionY = (Turbine.UI.Display.GetHeight() / 2) - self:GetHeight();
        end
        
        if( nil == self.settings.CalendarEntryArray ) then
          self.settings.CalendarEntryArray = { };
        end
end

-- --------------------------------------------------------------
-- SaveSettings
--
-- Description: save our internal settings to disk.  For this class,
-- this includes the position of the calendar window and the list of
-- events that have been created.
-- --------------------------------------------------------------
function CalendarWindow:SaveSettings()
  -- always save the dataLocation to the character scope!
  Turbine.PluginData.Save( Turbine.DataScope.Character, "CalendarDataSettings", self.dataLocation );
  
        -- save the settings depending on the dataLocation
  if( true == self.dataLocation.StoredOnCharacter ) then
    Turbine.PluginData.Save( Turbine.DataScope.Character, "CalendarWindowSettings", self.settings );
  else
    Turbine.PluginData.Save( Turbine.DataScope.Account, "CalendarWindowSettings", self.settings );
  end
end

Compare with Previous | Blame


All times are GMT -5. The time now is 01:22 PM.


Our Network
EQInterface | EQ2Interface | Minion | WoWInterface | ESOUI | LoTROInterface | MMOUI | Swtorui