Split things so that there can be a standalone zavai-calendar application
[gregoa/zavai.git] / src / widgets / calendar.vala
1 /*
2  * widgets/calendar - zavai calendar widget
3  *
4  * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 namespace zavai {
22 namespace widgets {
23
24 public class Calendar : Gtk.VBox
25 {
26         protected Gtk.Calendar calendar;
27         protected Gtk.ScrolledWindow scroll;
28         protected Gtk.TextBuffer text_buffer;
29         protected Gtk.TextView text;
30         protected int cur_year;
31         protected int cur_month;
32         protected int cur_day;
33         protected bool text_dirty;
34         protected Regex re_dayfile;
35
36         public Calendar()
37         {
38                 calendar = new Gtk.Calendar();
39                 calendar.day_selected += on_day_selected;
40                 calendar.month_changed += on_month_changed;
41                 pack_start(calendar, false, false, 0);
42
43                 text_buffer = new Gtk.TextBuffer(null);
44                 text_buffer.changed += on_textbuffer_changed;
45                 text = new Gtk.TextView.with_buffer(text_buffer);
46                 text.wrap_mode = Gtk.WrapMode.WORD;
47                 text.cursor_visible = true;
48                 text.editable = true;
49                 scroll = new Gtk.ScrolledWindow (null, null);
50                 scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
51                 scroll.add(text);
52                 pack_start(scroll, true, true, 0);
53
54                 re_dayfile = new Regex("[0-9][0-9]\\.txt");
55
56                 text_dirty = false;
57         }
58         
59         private void on_textbuffer_changed()
60         {
61                 text_dirty = true;
62         }
63
64         private string month_path(int year, int month)
65         {
66                 return "%s/cal/%04d/%02d".printf(zavai.config.homedir, year, month);
67         }
68
69         private string day_path(int year, int month, int day)
70         {
71                 return "%s/%02d.txt".printf(month_path(year, month), day);
72         }
73
74         private void on_month_changed()
75         {
76                 flush();
77                 calendar.clear_marks();
78                 string mpath = month_path(calendar.year, calendar.month + 1);
79                 Dir dir;
80                 try {
81                         dir = Dir.open(mpath);
82                 } catch (FileError e) {
83                         zavai.log.error(e.message);
84                         return;
85                 }
86                 while (true)
87                 {
88                         var d = dir.read_name();
89                         if (d == null) break;
90                         if (re_dayfile.match(d))
91                         {
92                                 calendar.mark_day((int)d.to_ulong(null, 10));
93                         }
94                 }
95         }
96
97         private void on_day_selected()
98         {
99                 flush();
100                 load(calendar.year, calendar.month + 1, calendar.day);
101                 // Scroll to beginning
102                 Gtk.TextIter iter;
103                 text_buffer.get_iter_at_offset(out iter, 0);
104                 Gtk.TextMark mark = text_buffer.create_mark(null, iter, true);
105                 text.scroll_mark_onscreen(mark);
106         }
107
108         private void load(int year, int month, int day)
109         {
110                 string path = day_path(year, month, day);
111                 if (!FileUtils.test (path, FileTest.IS_REGULAR))
112                         text_buffer.text = "";
113                 else
114                 {
115                         try {
116                                 string text;
117                                 FileUtils.get_contents(path, out text);
118                                 text_buffer.text = text;
119                         } catch (FileError e) {
120                                 zavai.log.error(e.message);
121                                 text_buffer.text = "";
122                         }
123                 }
124                 text_dirty = false;
125                 cur_year = year; cur_month = month; cur_day = day;
126         }
127
128         private void save(int year, int month, int day)
129         {
130                 string mpath = month_path(year, month);
131                 if (DirUtils.create_with_parents(mpath, 0777) < 0)
132                 {
133                         zavai.log.error("Cannot create directory " + mpath);
134                         return;
135                 }
136                 string path = day_path(year, month, day);
137                 try {
138                         FileUtils.set_contents(path, text_buffer.text);
139                 } catch (FileError e) {
140                         zavai.log.error(e.message);
141                 }
142                 text_dirty = false;
143
144                 if (calendar.year == year && calendar.month + 1 == month)
145                 {
146                         calendar.mark_day(day);
147                 }
148         }
149
150         public void flush()
151         {
152                 if (text_dirty)
153                         save(cur_year, cur_month, cur_day);
154         }
155
156         public void show_today()
157         {
158                 // Go to current date
159                 var now = Time.local(time_t());
160                 calendar.year = now.year + 1900;
161                 calendar.month = now.month;
162                 calendar.day = now.day;
163         }
164 }
165
166 }
167 }