[gnome-shell/datetime] Calendar updates
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/datetime] Calendar updates
- Date: Tue, 25 Jan 2011 15:10:01 +0000 (UTC)
commit a1440bdec721227994dbf89f9bea996e74e40ae0
Author: David Zeuthen <davidz redhat com>
Date: Tue Jan 25 09:55:41 2011 -0500
Calendar updates
- Reshuffle items to make it look more like the mockup
- Increase vertical spacing between event section ("Today") headings
and the event items (see mockup)
- Don't show the year in month-switcher and event list unless it's
a different year
- Include the day in the date heading
- Sort events in event list according to start time
- Respect 12h/24h setting in event list
- Support "All Day" events in CalendarTask abstraction
- Show "Nothing Scheduled" if there are no events
- Add a "Open Calendar" button
- Refactor some of the code
Signed-off-by: David Zeuthen <davidz redhat com>
data/theme/gnome-shell.css | 28 ++-----
js/ui/calendar.js | 169 ++++++++++++++++++++++++++++++--------------
js/ui/dateMenu.js | 49 ++++++++++---
3 files changed, 162 insertions(+), 84 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 4696262..5572a20 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -677,7 +677,7 @@ StTooltip StLabel {
.calendar-vertical-separator {
-stipple-width: 1px;
-stipple-color: #505050;
- width: 1em;
+ width: 1.5em;
}
#calendarPopup {
@@ -691,15 +691,8 @@ StTooltip StLabel {
padding: 10px;
}
-#calendarHBox {
- padding: 10px 20px;
-}
-
-#calendarVBox1 {
- spacing: 20px;
-}
-
.calendar {
+ padding: .4em 1.75em;
spacing-rows: 0px;
spacing-columns: 0px;
}
@@ -749,22 +742,24 @@ StTooltip StLabel {
}
.datemenu-date-label {
+ padding: .4em 1.75em;
font-size: 16px;
color: #ffffff;
}
.calendar-day-base {
font-size: 10px;
- padding: 5px 3px;
text-align: center;
+ width: 24px;
+ height: 24px;
}
.calendar-day-base:hover {
- background: #999999;
+ background: #777777;
}
.calendar-day-base:active {
- background: #666666;
+ background: #555555;
}
.calendar-day-heading {
@@ -820,6 +815,7 @@ StTooltip StLabel {
.events-day-header {
font-size: 14px;
color: rgba(153, 153, 153, 1.0);
+ padding: 0.3em;
}
.events-day-dayname {
@@ -852,14 +848,6 @@ StTooltip StLabel {
width: 200px;
}
-.events-no-events {
- font-weight: bold;
- padding-left: 40px;
- padding-right: 40px;
- font-size: 14px;
- color: rgba(153, 153, 153, 1.0);
-}
-
.open-calendar {
padding-bottom: 12px;
padding-left: 12px;
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index aea20de..2e89479 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -15,12 +15,19 @@ const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const WEEKDATE_HEADER_WIDTH_DIGITS = 3;
const SHOW_WEEKDATE_KEY = 'show-weekdate';
+// in org.gnome.desktop.interface
+const CLOCK_FORMAT_KEY = 'clock-format';
+
function _sameDay(dateA, dateB) {
return (dateA.getDate() == dateB.getDate() &&
dateA.getMonth() == dateB.getMonth() &&
dateA.getYear() == dateB.getYear());
}
+function _sameYear(dateA, dateB) {
+ return (dateA.getYear() == dateB.getYear());
+}
+
/* TODO: maybe needs config - right now we assume that Saturday and
* Sunday are non-work days (not true in e.g. Israel, it's Sunday and
* Monday there)
@@ -29,6 +36,43 @@ function _isWorkDay(date) {
return date.getDay() != 0 && date.getDay() != 6;
}
+function _getBeginningOfDay(date) {
+ let ret = new Date(date.getTime());
+ ret.setHours(0);
+ ret.setMinutes(0);
+ ret.setMilliseconds(0);
+ return ret;
+}
+
+function _getEndOfDay(date) {
+ let ret = new Date(date.getTime());
+ ret.setHours(23);
+ ret.setMinutes(59);
+ ret.setMilliseconds(999);
+ return ret;
+}
+
+function _formatTaskTime(task, clockFormat) {
+ let ret;
+ if (task.allDay) {
+ /* Translators: Shown in calendar event list for all day events */
+ ret = _("All Day");
+ } else {
+ switch (clockFormat) {
+ case '24h':
+ ret = task.date.toLocaleFormat('%H:%M');
+ break;
+
+ default:
+ /* explicit fall-through */
+ case '12h':
+ ret = task.date.toLocaleFormat('%l:%M %p');
+ break;
+ }
+ }
+ return ret;
+}
+
function _getCalendarWeekForDate(date) {
// Based on the algorithms found here:
// http://en.wikipedia.org/wiki/Talk:ISO_week_date
@@ -106,14 +150,15 @@ function _getEventDayAbbreviation(dayNumber) {
// Abstraction for an appointment/task in a calendar
-function CalendarTask(date, summary) {
- this._init(date, summary);
+function CalendarTask(date, summary, allDay) {
+ this._init(date, summary, allDay);
}
CalendarTask.prototype = {
- _init: function(date, summary) {
+ _init: function(date, summary, allDay) {
this.date = date;
this.summary = summary;
+ this.allDay = allDay;
}
};
@@ -153,52 +198,56 @@ FakeEventSource.prototype = {
// Generate fake events
//
- let now = new Date();
+ let midnightToday = _getBeginningOfDay(new Date());
let summary = '';
- now.setHours(0);
- now.setMinutes(0);
- now.setSeconds(0);
// '10-oclock pow-wow' is an event occuring IN THE PAST every four days at 10am
- for(let n = 0; n < 10; n++) {
- let t = new Date(now.getTime() - n * 4 * 86400 * 1000);
+ for (let n = 0; n < 10; n++) {
+ let t = new Date(midnightToday.getTime() - n * 4 * 86400 * 1000);
t.setHours(10);
summary = '10-oclock pow-wow (n=' + n + ')';
- this._fakeTasks.push(new CalendarTask(t, summary));
+ this._fakeTasks.push(new CalendarTask(t, summary, false));
}
// '11-oclock thing' is an event occuring every three days at 11am
- for(let n = 0; n < 10; n++) {
- let t = new Date(now.getTime() + n * 3 * 86400 * 1000);
+ for (let n = 0; n < 10; n++) {
+ let t = new Date(midnightToday.getTime() + n * 3 * 86400 * 1000);
t.setHours(11);
summary = '11-oclock thing (n=' + n + ')';
- this._fakeTasks.push(new CalendarTask(t, summary));
+ this._fakeTasks.push(new CalendarTask(t, summary, false));
}
// 'Weekly Meeting' is an event occuring every seven days at 1:45pm (two days displaced)
- for(let n = 0; n < 5; n++) {
- let t = new Date(now.getTime() + (n * 7 + 2) * 86400 * 1000);
+ for (let n = 0; n < 5; n++) {
+ let t = new Date(midnightToday.getTime() + (n * 7 + 2) * 86400 * 1000);
t.setHours(13);
t.setMinutes(45);
summary = 'Weekly Meeting (n=' + n + ')';
- this._fakeTasks.push(new CalendarTask(t, summary));
+ this._fakeTasks.push(new CalendarTask(t, summary, false));
+ }
+
+ // 'Fun All Day' is an all-day event occuring every fortnight (three days displayed)
+ for (let n = 0; n < 10; n++) {
+ let t = new Date(midnightToday.getTime() + (n * 14 + 3) * 86400 * 1000);
+ summary = 'Fun All Day (n=' + n + ')';
+ this._fakeTasks.push(new CalendarTask(t, summary, true));
}
// 'Get Married' is an event that actually reflects reality (Dec 4, 2010) :-)
- this._fakeTasks.push(new CalendarTask(new Date(2010, 11, 4, 16, 0), 'Get Married'));
+ this._fakeTasks.push(new CalendarTask(new Date(2010, 11, 4, 16, 0), 'Get Married', false));
// ditto for 'NE Patriots vs NY Jets'
- this._fakeTasks.push(new CalendarTask(new Date(2010, 11, 6, 20, 30), 'NE Patriots vs NY Jets'));
+ this._fakeTasks.push(new CalendarTask(new Date(2010, 11, 6, 20, 30), 'NE Patriots vs NY Jets', false));
// An event for tomorrow @6:30pm that is added/removed every five
// seconds (to check that the ::changed signal works)
- let transientEventDate = new Date(now.getTime() + 86400*1000);
+ let transientEventDate = new Date(midnightToday.getTime() + 86400 * 1000);
transientEventDate.setHours(18);
transientEventDate.setMinutes(30);
transientEventDate.setSeconds(0);
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
this._includeTransientEvent = false;
- this._transientEvent = new CalendarTask(transientEventDate, 'A Transient Event');
+ this._transientEvent = new CalendarTask(transientEventDate, 'A Transient Event', false);
this._transientEventCounter = 1;
},
@@ -223,16 +272,15 @@ FakeEventSource.prototype = {
}
if (this._includeTransientEvent && this._transientEvent.date >= begin && this._transientEvent.date <= end)
result.push(this._transientEvent);
+ result.sort(function(task1, task2) {
+ return task1.date.getTime() - task2.date.getTime();
+ });
return result;
},
hasTasks: function(day) {
- let dayBegin = new Date(day.getTime());
- let dayEnd = new Date(day.getTime());
- dayBegin.setHours(0);
- dayBegin.setMinutes(1);
- dayEnd.setHours(23);
- dayEnd.setMinutes(59);
+ let dayBegin = _getBeginningOfDay(day);
+ let dayEnd = _getEndOfDay(day);
let tasks = this.getTasks(dayBegin, dayEnd);
@@ -280,6 +328,7 @@ Calendar.prototype = {
}
// Find the ordering for month/year in the calendar heading
+ this._headerFormatWithoutYear = '%B';
switch (Gettext_gtk30.gettext('calendar:MY')) {
case 'calendar:MY':
this._headerFormat = '%B %Y';
@@ -417,7 +466,12 @@ Calendar.prototype = {
},
_update: function() {
- this._dateLabel.text = this.selectedDate.toLocaleFormat(this._headerFormat);
+ let now = new Date();
+
+ if (_sameYear(this.selectedDate, now))
+ this._dateLabel.text = this.selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
+ else
+ this._dateLabel.text = this.selectedDate.toLocaleFormat(this._headerFormat);
// Remove everything but the topBox and the weekday labels
let children = this.actor.get_children();
@@ -432,8 +486,6 @@ Calendar.prototype = {
let daysToWeekStart = (7 + iter.getDay() - this._weekStart) % 7;
iter.setTime(iter.getTime() - daysToWeekStart * MSECS_IN_DAY);
- let now = new Date();
-
let row = 2;
while (true) {
let button = new St.Button({ label: iter.getDate().toString() });
@@ -500,6 +552,8 @@ EventsList.prototype = {
this._date = new Date();
this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, this._update));
+ this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
+ this._desktopSettings.connect('changed', Lang.bind(this, this._update));
this._update();
},
@@ -516,10 +570,12 @@ EventsList.prototype = {
text: desc} ));
},
- _addPeriod: function(header, begin, end, includeDayName) {
+ _addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
let tasks = this._eventSource.getTasks(begin, end);
- if (tasks.length == 0)
+ let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
+
+ if (tasks.length == 0 && !showNothingScheduled)
return;
let vbox = new St.BoxLayout( {vertical: true} );
@@ -538,50 +594,59 @@ EventsList.prototype = {
for (let n = 0; n < tasks.length; n++) {
let task = tasks[n];
let dayString = _getEventDayAbbreviation(task.date.getDay());
- let timeString = task.date.toLocaleFormat('%I:%M %p'); // TODO: locale considerations
+ let timeString = _formatTaskTime(task, clockFormat);
let summaryString = task.summary;
this._addEvent(dayNameBox, timeBox, eventTitleBox, includeDayName, dayString, timeString, summaryString);
}
+
+ if (tasks.length == 0 && showNothingScheduled) {
+ let now = new Date();
+ /* Translators: Text to show if there are no events */
+ let nothingTask = new CalendarTask(now, _("Nothing Scheduled"), true);
+ let timeString = _formatTaskTime(nothingTask, clockFormat);
+ this._addEvent(dayNameBox, timeBox, eventTitleBox, false, "", timeString, nothingTask.summary);
+ }
},
_showOtherDay: function(day) {
this.actor.destroy_children();
- let dayBegin = new Date(day.getTime());
- let dayEnd = new Date(day.getTime());
- dayBegin.setHours(0);
- dayBegin.setMinutes(1);
- dayEnd.setHours(23);
- dayEnd.setMinutes(59);
- this._addPeriod(day.toLocaleFormat('%A, %B %d, %Y'), dayBegin, dayEnd, false);
+ let dayBegin = _getBeginningOfDay(day);
+ let dayEnd = _getEndOfDay(day);
+
+ let dayString;
+ let now = new Date();
+ if (_sameYear(day, now))
+ dayString = day.toLocaleFormat('%A, %B %d');
+ else
+ dayString = day.toLocaleFormat('%A, %B %d, %Y');
+ this._addPeriod(dayString, dayBegin, dayEnd, false, true);
},
_showToday: function() {
this.actor.destroy_children();
- let dayBegin = new Date();
- let dayEnd = new Date();
- dayBegin.setHours(0);
- dayBegin.setMinutes(1);
- dayEnd.setHours(23);
- dayEnd.setMinutes(59);
- this._addPeriod(_("Today"), dayBegin, dayEnd, false);
+ let now = new Date();
+ let dayBegin = _getBeginningOfDay(now);
+ let dayEnd = _getEndOfDay(now);
+ this._addPeriod(_("Today"), dayBegin, dayEnd, false, true);
dayBegin.setDate(dayBegin.getDate() + 1);
dayEnd.setDate(dayEnd.getDate() + 1);
- this._addPeriod(_("Tomorrow"), dayBegin, dayEnd, false);
+ this._addPeriod(_("Tomorrow"), dayBegin, dayEnd, false, true);
if (dayEnd.getDay() == 6 || dayEnd.getDay() == 0) {
dayBegin.setDate(dayEnd.getDate() + 1);
dayEnd.setDate(dayBegin.getDate() + 6 - dayBegin.getDay());
- this._addPeriod(_("Next week"), dayBegin, dayEnd, true);
+ this._addPeriod(_("Next week"), dayBegin, dayEnd, true, true);
return;
+ } else {
+ let d = 6 - dayEnd.getDay() - 1;
+ dayBegin.setDate(dayBegin.getDate() + 1);
+ dayEnd.setDate(dayEnd.getDate() + 1 + d);
+ this._addPeriod(_("This week"), dayBegin, dayEnd, true, true);
}
- let d = 6 - dayEnd.getDay() - 1;
- dayBegin.setDate(dayBegin.getDate() + 1);
- dayEnd.setDate(dayEnd.getDate() + 1 + d);
- this._addPeriod(_("This week"), dayBegin, dayEnd, true);
},
// Sets the event list to show events from a specific date
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
index 8616735..35f6558 100644
--- a/js/ui/dateMenu.js
+++ b/js/ui/dateMenu.js
@@ -55,8 +55,8 @@ DateMenuButton.prototype = {
let hbox;
let vbox;
- this._eventSource = new Calendar.EmptyEventSource();
- //this._eventSource = new Calendar.FakeEventSource();
+ //this._eventSource = new Calendar.EmptyEventSource();
+ this._eventSource = new Calendar.FakeEventSource();
// TODO: write e.g. EvolutionEventSource
PanelMenu.Button.prototype._init.call(this, St.Align.START);
@@ -64,12 +64,12 @@ DateMenuButton.prototype = {
this._clock = new St.Label();
this.actor.set_child(this._clock);
- hbox = new St.BoxLayout({name: 'calendarHBox'});
+ hbox = new St.BoxLayout();
this.menu.addActor(hbox);
// Fill up the first column
- vbox = new St.BoxLayout({vertical: true, name: 'calendarVBox1'});
+ vbox = new St.BoxLayout({vertical: true});
hbox.add(vbox);
// Date
@@ -87,18 +87,33 @@ DateMenuButton.prototype = {
}));
vbox.add(this._calendar.actor);
+ //item = new St.Button({style_class: 'popup-menu-item', label: 'foobar'});
+ //vbox.add(item);
+ item = new PopupMenu.PopupSeparatorMenuItem();
+ item.actor.remove_actor(item._drawingArea);
+ vbox.add(item._drawingArea);
+ item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
+ item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
+ vbox.add(item.actor);
+
// Add vertical separator
item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
pseudo_class: 'highlighted' });
- item.set_width(25); // TODO: don't hard-code the width
item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
hbox.add(item);
// Fill up the second column
//
+ vbox = new St.BoxLayout({vertical: true});
+ hbox.add(vbox);
+
// Event list
- hbox.add(this._eventList.actor);
+ vbox.add(this._eventList.actor);
+
+ item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
+ item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
+ vbox.add(item.actor, {y_align : St.Align.END, expand : true, y_fill : false});
// Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
@@ -113,12 +128,12 @@ DateMenuButton.prototype = {
// Done with hbox for calendar and event list
// Add separator
- item = new PopupMenu.PopupSeparatorMenuItem();
- this.menu.addMenuItem(item);
+ //item = new PopupMenu.PopupSeparatorMenuItem();
+ //this.menu.addMenuItem(item);
// Add button to get to the Date and Time settings
- this.menu.addAction(_("Date and Time Settings"),
- Lang.bind(this, this._onPreferencesActivate));
+ //this.menu.addAction(_("Date and Time Settings"),
+ // Lang.bind(this, this._onPreferencesActivate));
// Track changes to clock settings
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
@@ -185,8 +200,10 @@ DateMenuButton.prototype = {
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
- /* Translators: This is the date format to use */
- dateFormat = _("%B %e, %Y");
+ /* Translators: This is the date format to use when the calendar popup is
+ * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
+ */
+ dateFormat = _("%A %B %e, %Y");
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClockAndDate));
@@ -194,6 +211,14 @@ DateMenuButton.prototype = {
},
_onPreferencesActivate: function() {
+ this.menu.close();
Util.spawnDesktop('gnome-datetime-panel');
},
+
+ _onOpenCalendarActivate: function() {
+ this.menu.close();
+ // TODO: pass '-c calendar' (to force the calendar at startup)
+ // TODO: pass the selected day
+ Util.spawnDesktop('evolution');
+ },
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]