Dk75 schedule.module (en)

From Conky PitStop

Revision as of 11:34, 15 June 2012 by DK75 (Talk | contribs)
Jump to: navigation, search

dk75_schedule.module

User:DK75

 Language   English   Français   


Calendar/schedule for One4All project

Dk75-schedule.module.png

File:Dk75 schedule.module-1.2.3.tar.gz

	--[[
  schedule.module
  Displays calendars (current mont and as many previous and next month as you like - additional months are evenly divided betwen previous and next periods) with additional text displayed in every day cell.
  Either it could be some short text message or colored background.
  Data format of data/schedule-${year}-${month}.txt file (each months with it's own file):
     day	text
     day	text
	
  eg.
     1	9:00		# some event at 9:00 at first day
     2	holiday		# holiday event at second day
     3	x		# colored box at thrid day
	
  See example files in data/ directory.
	
  changelog:
  v 1.2.3 first public release
  --]]
	
  local modname = ...
  local M = {}
  _G[modname] = M
  package.loaded[modname] = M
	
	
	
  --[[
  ###############################################################################
  ###                              SETTINGS                                   ###
  ###############################################################################
  --]]
	
  local settings_table = {
     {	
        drawGrid			= false,	--draw helper grid (true) or don't (false)
        horizontal			= true,		--should graph be horizontaly (true) or verticaly (false) aligned
        date_align			= 'left',	--align of date number: 'left', 'right' or 'center'
        schedule_align			= 'right',	--align of schedule: 'left', 'right' or 'center'
        calendar_update			= 300,		--number of conky updates after which calendar will update
        numberOfMonth			= 3,		--number of month to include in graph
        cellSize			= 50,		--one day cell size both width and height (square cell)
        cellGapDivider			= 20,		--is used to calculate gap between of cels as "cellGap = cellSize / cellGapDivider"
        graphGapMultiplier		= 3,		--is used to calculate gap between of graphs as "graphGap = cellGap * graphGapMultiplier"
        corner_rG			= 10,		--rounding of graph corners in percents
        corner_rC			= 50,		--rounding of cell corners in percents
        startX				= 0,		--upper left corner x-axis start of graph
        startY				= 0,		--upper left corner y-axis start of graph
        color_G				= 0x000000,	--graph shadow color
        alpha_G				= 0.7,		--graph shadow alpha
        color_C				= 0x00afff,	--cell color
        alpha_C				= 0.5,		--cell alpha
        color_W				= 0x00ff00,	--weekday color
        color_Sa			= 0xffff00,	--saturday color
        color_Su			= 0xff0000,	--sunday color
        color_M				= 0xffffff,	--month and separation bar color
        color_N				= 0xff0000,	--current day rim color
        alpha_N				= 1,		--current day rim alpha
	
        -- don't modyfi settings below
	
        sizeW				= 0,		--don't modyfi - it's no use to set this because it will be rewrited after start
        sizeH				= 0,		--don't modyfi - it's no use to set this because it will be rewrited after start
        sizeAll				= 0,		--don't modyfi - it's no use to set this because it will be rewrited after start
        cellGap				= 0,		--don't modyfi - it's no use to set this because it will be rewrited after start
        graphGap			= 0,		--don't modyfi - it's no use to set this because it will be rewrited after start
        _date				= os.date('*t'),	--don't modyfi
        _calendar			= {},			--don't modyfi
        isMondayFirtsDayOfTheWeek	= tonumber(one4all_main.os_capture('locale first_weekday','raw')) - 1,	--don't modyfi
     },
  }
			
  --[[
  ###############################################################################
  ###                           END OF SETTINGS                               ###
  ###############################################################################
  --]]
	
	
	
	
  function M.errors(t, _errorNo)
     local sizeW, sizeH = t.sizeW+t.startX, t.sizeH+t.startY
     if t.horizontal then sizeW = t.sizeAll+t.startX else sizeH = t.sizeAll+t.startY end
	
     local _errors = {
        "Check size error! Schedule graph " .. sizeW .. "x" .. sizeH .. " is bigger than Conky window " .. conky_window.width .. "x" .. conky_window.height .. " !!!",
        "Warning! Can't read one or all schedule text file",
     }
		
     print(_errors[_errorNo])
  end
	
  function M.check_size(t)
     t.cellGap = math.floor(t.cellSize/t.cellGapDivider)
     t.graphGap = math.floor(t.cellGap*t.graphGapMultiplier)
     t.sizeW = (t.cellSize + t.cellGap) * 7
     t.sizeH = math.floor(t.sizeW + t.cellSize * 0.5)
     if t.horizontal
     then
        t.sizeAll = t.sizeW * t.numberOfMonth + t.graphGap * (t.numberOfMonth -1)
        --print(t.sizeAll+t.startX, t.sizeH+t.startY)
        --print("Cell size: " .. t.cellSize , "Cell gap: " .. t.cellGap , "Size of 1 graph: " .. t.sizeW .. " x " .. t.sizeH, "Graph gap: " .. t.graphGap, "Size: " .. t.sizeAll .. " x " .. t.sizeH)
        if t.sizeAll + t.startX > conky_window.width or t.sizeH + t.startY > conky_window.height then return false else return true end
     else
        t.sizeAll = t.sizeH * t.numberOfMonth + t.graphGap * (t.numberOfMonth -1)
        --print(t.sizeAll+t.startY, t.sizeW+t.startX)
        --print("Cell size: " .. t.cellSize , "Cell gap: " .. t.cellGap , "Size of 1 graph: " .. t.sizeW .. " x " .. t.sizeH, "Graph gap: " .. t.graphGap, "Size: " .. t.sizeW .. " x " .. t.sizeAll)
        if t.sizeAll + t.startY > conky_window.height or t.sizeW + t.startX > conky_window.width then return false else return true end
     end
  end
	
  function M.setlocale()
     local _locale = os.setlocale(nil, 'ctype')
     os.setlocale(_locale, 'all')
  end
	
  function M.init_calendar(t)
     local _date, _tmp, dateMod, dateF, _t, _error = {}, {}, 0, , 0, 0
     _date.year, _date.month, _date.day = t._date.year, t._date.month-math.floor(t.numberOfMonth/2), 1
     if t.isMondayFirtsDayOfTheWeek == 1
        then dateMod, dateF = 0, "%u"
        else dateMod, dateF = 1, "%w"
     end
     for i=1, t.numberOfMonth, 1
     do
        _t = 0
        for j=1, 42, 1
        do
           if j < os.date(dateF, os.time(_date))+dateMod then _tmp[j] = { day = , schedule =  }; _t = j
           elseif j == _date.day+_t then _tmp[j] = { day = os.date('%d', os.time(_date)), schedule =  }; _date.day = _date.day+1
              if _date.day ~= tonumber(os.date('%d', os.time(_date))) then _date.day = _date.day-1 end
           else _tmp[j] = { day = , schedule =  }
           end
        end
        --print('/data/schedule-' .. _date.year .. "-" .. string.format('%02d', _date.month) .. '.txt')
        if io.open(_conky_path .. '/data/schedule-' .. _date.year .. "-" .. string.format('%02d', _date.month) .. '.txt') then 
           for l in io.lines(_conky_path .. '/data/schedule-' .. _date.year .. "-" .. string.format('%02d', _date.month) .. '.txt') do
              local _day, _schedule = l:match '(%S+)%s+(%S+)'
              if _day == nil then break end
              local j=0
              repeat
                 j=j+1
              until _tmp[j].day == string.format('%02d', _day)
              _tmp[j].schedule = _schedule
           end
        else _error=2
        end
        t._calendar[i]=_tmp
        _tmp = {}
        _date.day=1
        _date.month=_date.month+1
     end
     return _error
  end
	
  function M.align(textAlign, textSize, cellSize, cellGap)
     if textAlign == 'center' then return cellGap/2 + cellSize/2 - textSize/2
     elseif textAlign == 'left' then
        if textSize > cellSize/2 - cellGap*2 then return cellGap*2
        else return cellGap/2 + cellSize/2 - textSize end
     else
        if textSize > cellSize/2 - cellGap*2 then return cellGap/2 + cellSize - textSize - cellGap*2
        else return cellGap/2 + cellSize/2 end
     end
  end
	
  function M.draw_box(x, y, width, height, rounding, color, alpha, nofill)
     local roundingW = math.floor(width * rounding / 200)
     local roundingH = math.floor(height * rounding / 200)
     cairo_move_to(cr, x+roundingW, y)
     cairo_line_to(cr, x+width-roundingW, y)
     cairo_curve_to(cr, x+width-roundingW, y, x+width, y, x+width, y+roundingH)
     cairo_line_to(cr, x+width, y+height-roundingH)
     cairo_curve_to(cr, x+width, y+height-roundingH, x+width, y+height, x+width-roundingW, y+height)
     cairo_line_to(cr, x+roundingW, y+height)
     cairo_curve_to(cr, x+roundingW, y+height, x, y+height, x, y+height-roundingH)
     cairo_line_to(cr, x, y+roundingH)
     cairo_curve_to(cr, x, y+roundingH, x, y, x+roundingW, y)
     cairo_close_path(cr)
     cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(color, alpha))
     if nofill then cairo_set_line_width (cr, width/20); cairo_stroke(cr) else cairo_fill(cr) end
     cairo_set_line_width (cr, 1)
  end
	
  function M.draw_grid(t, modX, modY)
     cairo_set_source_rgba(cr, 1, 1, 1, 0.5)
     cairo_move_to(cr, t.startX+modX, t.startY+modY)
     cairo_line_to(cr, t.startX+modX+t.sizeW, t.startY+modY)
     cairo_line_to(cr, t.startX+modX+t.sizeW, t.startY+modY+t.sizeH)
     cairo_line_to(cr, t.startX+modX, t.startY+modY+t.sizeH)
     cairo_line_to(cr, t.startX+modX, t.startY+modY)
     cairo_stroke(cr)
     for i=1, 7, 1
     do
        cairo_move_to(cr, t.startX+modX+(t.cellSize+t.cellGap)*i, t.startY+modY)
        cairo_line_to(cr, t.startX+modX+(t.cellSize+t.cellGap)*i, t.startY+modY+t.sizeH)
        cairo_move_to(cr, t.startX+modX, t.startY+modY+(t.cellSize+t.cellGap)*i+t.cellSize*0.5)
        cairo_line_to(cr, t.startX+modX+t.sizeW, t.startY+modY+(t.cellSize+t.cellGap)*i+t.cellSize*0.5)
        cairo_stroke(cr)
     end
  end
	
  function M.draw_graph(t)
     local modX, modY, weekS, dateF = 0, 0, 0, ""
     local _date, _week = {}, {}
     _date.year = t._date.year
     _date.month = t._date.month-math.floor(t.numberOfMonth/2)
     _date.day = 1
     if t.isMondayFirtsDayOfTheWeek == 1
        then weekS, dateF, _week.day, _week.month, _week.year = 1, "%u", 1, 12, 1997
        else weekS, dateF, _week.day, _week.month, _week.year = 0, "%w", 7, 12, 1997
     end
     if t.horizontal then modX = t.sizeW + t.graphGap else modY = t.sizeH + t.graphGap end
     for i=0, t.numberOfMonth-1, 1
     do
        -- draw shadow box and/or grid for every graph
        M.draw_box(t.startX+(modX*i), t.startY+(modY*i), t.sizeW, t.sizeH, t.corner_rG, t.color_G, t.alpha_G)
        if t.drawGrid then M.draw_grid(t, modX*i, modY*i) end
			
        local extents = cairo_text_extents_t:create() -- initialize text_extents structure (generic, a must be for following functions)
			
        -- print month name
        cairo_select_font_face(cr, "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD)
        cairo_set_font_size(cr, t.cellSize/2)
        local _text = os.date('%B', os.time(_date))
        cairo_text_extents(cr, _text, extents)
        cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_M, 1))
        cairo_move_to(cr, t.startX+modX*i+t.sizeW/2-extents.width/2, t.startY+modY*i+math.floor(t.cellSize/2)+t.cellGap*2)
        cairo_show_text(cr, _text)
        cairo_stroke(cr)
        _date.month = _date.month+1
	
        -- print week days names
        cairo_select_font_face(cr, "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD)
        cairo_set_font_size(cr, t.cellSize/2.8)
        for j=weekS, weekS+6, 1
        do
           _week.day = j
           local _text = os.date('%a', os.time(_week))
           cairo_text_extents(cr, _text, extents)
           cairo_move_to(cr, t.startX+modX*i+((t.cellSize+t.cellGap)*(j-weekS))+t.cellGap/2+t.cellSize/2-extents.width/2, t.startY+modY*i+t.cellSize+t.cellGap*2)
           if j==0 or j==7 then cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_Su, 1))
              elseif j==6 then cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_Sa, 1))
              else cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_W, 1))
           end
           cairo_show_text(cr, _text)
           cairo_stroke(cr)
        end
			
        -- draw separation bar
        local _pat = cairo_pattern_create_linear(0, t.startY+modY*i+t.cellSize*1.5-t.cellGap/2-t.cellSize/5, 0, t.startY+modY*i+t.cellSize*1.5-t.cellGap/2)
        cairo_pattern_add_color_stop_rgba(_pat, 0, one4all_cairo.rgb2rgba(0x000000, 0.2))
        cairo_pattern_add_color_stop_rgba(_pat, 0.1, one4all_cairo.rgb2rgba(t.color_M, 0.2))
        cairo_pattern_add_color_stop_rgba(_pat, 0.3, one4all_cairo.rgb2rgba(t.color_M, 0.7))
        cairo_pattern_add_color_stop_rgba(_pat, 0.4, one4all_cairo.rgb2rgba(t.color_M, 0.9))
        cairo_pattern_add_color_stop_rgba(_pat, 0.5, one4all_cairo.rgb2rgba(t.color_M, 1))
        cairo_pattern_add_color_stop_rgba(_pat, 0.6, one4all_cairo.rgb2rgba(t.color_M, 0.9))
        cairo_pattern_add_color_stop_rgba(_pat, 0.7, one4all_cairo.rgb2rgba(t.color_M, 0.7))
        cairo_pattern_add_color_stop_rgba(_pat, 0.9, one4all_cairo.rgb2rgba(t.color_M, 0.2))
        cairo_pattern_add_color_stop_rgba(_pat, 1, one4all_cairo.rgb2rgba(0x000000, 0.2))
        cairo_set_source(cr, _pat)
        cairo_move_to(cr, t.startX+modX*i+t.cellGap*4, t.startY+modY*i+t.cellSize*1.5-t.cellGap/2-t.cellSize/10)
        cairo_line_to(cr, t.startX+modX*i+t.sizeW-t.cellGap*4, t.startY+modY*i+t.cellSize*1.5-t.cellGap/2-t.cellSize/10)
        cairo_set_line_width (cr, t.cellSize/5)
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND)
        cairo_stroke(cr)
        cairo_pattern_destroy(_pat)
        cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT)
        cairo_set_line_width (cr, 1)
			
        -- print schedule
        cairo_select_font_face(cr, "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD)
        for j=1, 42, 1 do
           if j < 14 and t._calendar[i+1][j].day == nil then break end
           local _t_int, _t_frac = math.modf(j/7); if _t_int > 0 and _t_frac == 0 then _t_int = _t_int - 1 end
           if t._calendar[i+1][j].schedule == 'x' then
              M.draw_box(t.startX+modX*i+(t.cellSize+t.cellGap)*(j-1-_t_int*7)+t.cellGap, t.startY+modY*i+t.cellSize*1.5+(t.cellSize+t.cellGap)*_t_int+t.cellGap*2, t.cellSize-t.cellGap, t.cellSize-t.cellGap, t.corner_rC, t.color_C, t.alpha_C)
           elseif t._calendar[i+1][j].schedule ~= nil then
              local _text = t._calendar[i+1][j].schedule
              local _div = 1
              repeat
                 cairo_set_font_size(cr, (t.cellSize/2.5)/_div)
                 cairo_text_extents(cr, _text, extents)
                 _div = _div + 0.2
              until extents.width < t.cellSize-t.cellGap*4
              local _position = M.align(t.schedule_align, extents.width, t.cellSize, t.cellGap)
              cairo_move_to(cr, t.startX+modX*i+(t.cellSize+t.cellGap)*(j-1-_t_int*7)+_position, t.startY+modY*i+t.cellSize*1.5+(t.cellSize+t.cellGap)*_t_int+t.cellGap+t.cellSize/2+extents.height+t.cellGap/2)
              cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_M, 1))
              cairo_show_text(cr, _text)
              cairo_stroke(cr)
           end
        end
	
        -- print month days numbers
        cairo_select_font_face(cr, "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD)
        cairo_set_font_size(cr, t.cellSize/3)
        --cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_M, 1))
        for j in pairs(t._calendar[i+1])
        do
           --print("Graph No.: " .. i, "Filed No.: " .. j, "Day: " .. t._calendar[i+1][j].day)
           if t._calendar[i+1][j] ~=  then
              local _t_int, _t_frac = math.modf(j/7); if _t_int > 0 and _t_frac == 0 then _t_int = _t_int - 1 end
              local _text = t._calendar[i+1][j].day
              cairo_text_extents(cr, _text, extents)
              local _position = M.align(t.date_align, extents.width, t.cellSize, t.cellGap)
              if ( j-_t_int*7==1 and t.isMondayFirtsDayOfTheWeek~=1 ) or ( j-_t_int*7==7 and t.isMondayFirtsDayOfTheWeek==1 ) then cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_Su, 1))
                 elseif ( j-_t_int*7==6 and t.isMondayFirtsDayOfTheWeek==1 ) or ( j-_t_int*7==7 and t.isMondayFirtsDayOfTheWeek~=1 ) then cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_Sa, 1))
                 else cairo_set_source_rgba(cr, one4all_cairo.rgb2rgba(t.color_W, 1))
              end
              cairo_move_to(cr, t.startX+modX*i+(t.cellSize+t.cellGap)*(j-1-_t_int*7)+_position, t.startY+modY*i+t.cellSize*1.5+(t.cellSize+t.cellGap)*_t_int+t.cellGap+t.cellSize/2-t.cellGap/2)
              cairo_show_text(cr, _text)
              cairo_stroke(cr)
           end
        end
     end
		
     -- draw rim
     local _nowGraph = math.floor(t.numberOfMonth/2)
     local _nowDay = os.date('%d'); --_nowDay = '30'
     local _nowCell = 0
     repeat
        _nowCell=_nowCell+1
     until _nowDay == t._calendar[_nowGraph+1][_nowCell].day
     local _t_int, _t_frac = math.modf(_nowCell/7); if _t_int > 0 and _t_frac == 0 then _t_int = _t_int - 1 end
     M.draw_box(t.startX+modX*_nowGraph+(t.cellSize+t.cellGap)*(_nowCell-1-_t_int*7)+t.cellGap, t.startY+modY*_nowGraph+t.cellSize*1.5+(t.cellSize+t.cellGap)*_t_int+t.cellGap*2, t.cellSize-t.cellGap, t.cellSize-t.cellGap, t.corner_rC, t.color_N, t.alpha_N, true)
  end
	
  function M.schedule(t)
     local _error = 0
     if not M.check_size(t) then return 1 end
     if t._calendar[1] == nil then _error = M.init_calendar(t); end
     local _upInt, _upFrac = math.modf(tonumber(conky_parse("${updates}"))/t.calendar_update)
     if _upFrac == 0 then t._date = os.date('*t'); _error = M.init_calendar(t); end
     M.draw_graph(t)
     return _error
  end
	
	
	
  M.setlocale()
  --[[
  ###############################################################################
  ###                            MODULE MAIN LOOP                             ###
  ###############################################################################
  --]]
  function M.main()
          for i in pairs(settings_table) do
              local _error = M.schedule(settings_table[i])
              if _error > 0 then M.errors(settings_table[i], _error); return end
          end
  end
Personal tools
Namespaces
Variants
Actions
Navigation
English
Français
Toolbox