dateMenu: Replace EventsList with MessageList

Turn the existing EventsList into a MessageListSection and add the
message list to the calendar drop-down. The new events list only
displays events for the currently selected day, but in a more
structured and friendlier way than the old one.

https://bugzilla.gnome.org/show_bug.cgi?id=744817
This commit is contained in:
Florian Müllner 2014-12-11 18:29:17 +01:00
parent 464f552dd2
commit e850d9e29b
4 changed files with 109 additions and 213 deletions

@ -1 +1 @@
Subproject commit e260e8a5bcc5907bbf3b4b3cc0df5bf11ff49b59
Subproject commit f0fd5e109ff5499f42f7c6d31b4308b82f6b5879

View File

@ -745,40 +745,6 @@ StScrollBar {
padding: 5px;
spacing: 5px; }
.events-table {
width: 15em;
spacing-columns: 1em;
padding: 0 1.4em; }
.events-table:ltr {
padding-right: 1.9em; }
.events-table:rtl {
padding-left: 1.9em; }
.events-day-header {
font-weight: bold;
color: #d6d6d1;
padding-left: 0;
padding-top: 1.2em; }
.events-day-header:first-child {
padding-top: 0; }
.events-day-dayname {
color: #d6d6d1;
text-align: left;
min-width: 20px; }
.events-day-dayname:rtl {
text-align: right; }
.events-day-dayname .events-day-time {
text-align: right; }
.events-day-dayname .events-day-time:rtl {
text-align: left; }
.events-day-dayname .events-day-task {
color: #d6d6d1; }
.events-day-dayname .events-day-task:ltr {
padding-left: 8px; }
.events-day-dayname .events-day-task:rtl {
padding-right: 8px; }
.system-switch-user-submenu-icon {
icon-size: 24px;
border: 1px solid rgba(238, 238, 236, 0.4); }

View File

@ -121,31 +121,6 @@ function _getCalendarDayAbbreviation(dayNumber) {
return abbreviations[dayNumber];
}
function _getEventDayAbbreviation(dayNumber) {
let abbreviations = [
/* Translators: Event list abbreviation for Sunday.
*
* NOTE: These list abbreviations are normally not shown together
* so they need to be unique (e.g. Tuesday and Thursday cannot
* both be 'T').
*/
C_("list sunday", "Su"),
/* Translators: Event list abbreviation for Monday */
C_("list monday", "M"),
/* Translators: Event list abbreviation for Tuesday */
C_("list tuesday", "T"),
/* Translators: Event list abbreviation for Wednesday */
C_("list wednesday", "W"),
/* Translators: Event list abbreviation for Thursday */
C_("list thursday", "Th"),
/* Translators: Event list abbreviation for Friday */
C_("list friday", "F"),
/* Translators: Event list abbreviation for Saturday */
C_("list saturday", "S")
];
return abbreviations[dayNumber];
}
function _fixMarkup(text, allowMarkup) {
if (allowMarkup) {
// Support &, ", ', < and >, escape all other
@ -1176,116 +1151,36 @@ const MessageListSection = new Lang.Class({
});
Signals.addSignalMethods(MessageListSection.prototype);
const EventsList = new Lang.Class({
Name: 'EventsList',
const EventsSection = new Lang.Class({
Name: 'EventsSection',
Extends: MessageListSection,
_init: function() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this.actor = new St.Widget({ style_class: 'events-table',
layout_manager: layout });
layout.hookup_style(this.actor);
this._date = new Date();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', Lang.bind(this, this._update));
this._weekStart = Shell.util_get_week_start();
this._desktopSettings.connect('changed', Lang.bind(this, this._reloadEvents));
this._eventSource = new EmptyEventSource();
this.parent('');
Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._appInstalledChanged));
this._appInstalledChanged();
},
setEventSource: function(eventSource) {
this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, this._update));
this._eventSource.connect('changed', Lang.bind(this, this._reloadEvents));
},
_addEvent: function(event, index, includeDayName, periodBegin, periodEnd) {
let dayString;
if (includeDayName) {
if (event.date >= periodBegin)
dayString = _getEventDayAbbreviation(event.date.getDay());
else /* show event end day if it began earlier */
dayString = _getEventDayAbbreviation(event.end.getDay());
} else {
dayString = '';
_updateTitle: function() {
let now = new Date();
if (_sameDay(this._date, now)) {
this._title.label = _("Events");
return;
}
let dayLabel = new St.Label({ style_class: 'events-day-dayname',
text: dayString,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START });
dayLabel.clutter_text.line_wrap = false;
dayLabel.clutter_text.ellipsize = false;
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
let layout = this.actor.layout_manager;
layout.attach(dayLabel, rtl ? 2 : 0, index, 1, 1);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
let timeString = _formatEventTime(event, clockFormat, periodBegin, periodEnd);
let timeLabel = new St.Label({ style_class: 'events-day-time',
text: timeString,
y_align: Clutter.ActorAlign.START });
timeLabel.clutter_text.line_wrap = false;
timeLabel.clutter_text.ellipsize = false;
let preEllipsisLabel = new St.Label({ style_class: 'events-day-time-ellipses',
text: ELLIPSIS_CHAR,
y_align: Clutter.ActorAlign.START });
let postEllipsisLabel = new St.Label({ style_class: 'events-day-time-ellipses',
text: ELLIPSIS_CHAR,
y_align: Clutter.ActorAlign.START });
if (event.allDay || event.date >= periodBegin)
preEllipsisLabel.opacity = 0;
if (event.allDay || event.end <= periodEnd)
postEllipsisLabel.opacity = 0;
let timeLabelBoxLayout = new St.BoxLayout();
timeLabelBoxLayout.add(preEllipsisLabel);
timeLabelBoxLayout.add(timeLabel);
timeLabelBoxLayout.add(postEllipsisLabel);
layout.attach(timeLabelBoxLayout, 1, index, 1, 1);
let titleLabel = new St.Label({ style_class: 'events-day-task',
text: event.summary,
x_expand: true });
titleLabel.clutter_text.line_wrap = true;
titleLabel.clutter_text.ellipsize = false;
layout.attach(titleLabel, rtl ? 0 : 2, index, 1, 1);
},
_addPeriod: function(header, index, periodBegin, periodEnd, includeDayName, showNothingScheduled) {
let events = this._eventSource.getEvents(periodBegin, periodEnd);
if (events.length == 0 && !showNothingScheduled)
return index;
let label = new St.Label({ style_class: 'events-day-header', text: header });
let layout = this.actor.layout_manager;
layout.attach(label, 0, index, 3, 1);
index++;
for (let n = 0; n < events.length; n++) {
this._addEvent(events[n], index, includeDayName, periodBegin, periodEnd);
index++;
}
if (events.length == 0 && showNothingScheduled) {
/* Translators: Text to show if there are no events */
let nothingEvent = new CalendarEvent(periodBegin, periodBegin, _("Nothing Scheduled"), true);
this._addEvent(nothingEvent, index, false, periodBegin, periodEnd);
index++;
}
return index;
},
_showOtherDay: function(day) {
this.actor.destroy_all_children();
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
let dayFormat;
let now = new Date();
if (_sameYear(day, now))
if (_sameYear(this._date, now))
/* Translators: Shown on calendar heading when selected day occurs on current year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %d"));
@ -1293,62 +1188,90 @@ const EventsList = new Lang.Class({
/* Translators: Shown on calendar heading when selected day occurs on different year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %d, %Y"));
let dayString = day.toLocaleFormat(dayFormat);
this._addPeriod(dayString, 0, dayBegin, dayEnd, false, true);
this._title.label = this._date.toLocaleFormat(dayFormat);
},
_showToday: function() {
this.actor.destroy_all_children();
let index = 0;
let now = new Date();
let dayBegin = _getBeginningOfDay(now);
let dayEnd = _getEndOfDay(now);
index = this._addPeriod(_("Today"), index, dayBegin, dayEnd, false, true);
let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000);
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
index = this._addPeriod(_("Tomorrow"), index, tomorrowBegin, tomorrowEnd, false, true);
let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7;
if (dayInWeek < 5) {
/* If now is within the first 5 days we show "This week" and
* include events up until and including Saturday/Sunday
* (depending on whether a week starts on Sunday/Monday).
*/
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000);
index = this._addPeriod(_("This week"), index, thisWeekBegin, thisWeekEnd, true, false);
} else {
/* otherwise it's one of the two last days of the week ... show
* "Next week" and include events up until and including *next*
* Saturday/Sunday
*/
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000);
index = this._addPeriod(_("Next week"), index, nextWeekBegin, nextWeekEnd, true, false);
}
},
// Sets the event list to show events from a specific date
setDate: function(date) {
if (!_sameDay(date, this._date)) {
this._date = date;
this._update();
}
},
_update: function() {
_reloadEvents: function() {
if (this._eventSource.isLoading)
return;
let today = new Date();
if (_sameDay (this._date, today)) {
this._showToday();
} else {
this._showOtherDay(this._date);
this._reloading = true;
this._list.destroy_all_children();
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
let events = this._eventSource.getEvents(periodBegin, periodEnd);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
for (let i = 0; i < events.length; i++) {
let event = events[i];
let title = _formatEventTime(event, clockFormat, periodBegin, periodEnd);
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (event.date < periodBegin && !event.allDay) {
if (rtl)
title = title + ELLIPSIS_CHAR;
else
title = ELLIPSIS_CHAR + title;
}
if (event.end > periodEnd && !event.allDay) {
if (rtl)
title = ELLIPSIS_CHAR + title;
else
title = title + ELLIPSIS_CHAR;
}
this.addMessage(new Message(title, event.summary), false);
}
this._reloading = false;
this._sync();
},
_appInstalledChanged: function() {
this._calendarApp = undefined;
this._title.reactive = (this._getCalendarApp() != null);
},
_getCalendarApp: function() {
if (this._calendarApp !== undefined)
return this._calendarApp;
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
if (apps && (apps.length > 0)) {
let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
let defaultInRecommended = apps.some(function(a) { return a.equal(app); });
this._calendarApp = defaultInRecommended ? app : apps[0];
} else {
this._calendarApp = null;
}
return this._calendarApp;
},
_onTitleClicked: function() {
this.parent();
let app = this._getCalendarApp();
if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context(0, -1));
},
setDate: function(date) {
this.parent(date);
this._updateTitle();
this._reloadEvents();
},
_syncVisible: function() {
this.actor.visible = !this.empty || !this._isToday();
},
_sync: function() {
if (this._reloading)
return;
this.parent();
}
});
@ -1396,6 +1319,9 @@ const MessageList = new Lang.Class({
y_align: Clutter.ActorAlign.START });
this._scrollView.add_actor(this._sectionList);
this._sections = new Map();
this._eventsSection = new EventsSection();
this._addSection(this._eventsSection);
},
_addSection: function(section) {
@ -1444,6 +1370,10 @@ const MessageList = new Lang.Class({
this._placeholder.actor.visible = showPlaceholder;
},
setEventSource: function(eventSource) {
this._eventsSection.setEventSource(eventSource);
},
setDate: function(date) {
for (let section of this._sections.keys())
section.setDate(date);

View File

@ -104,7 +104,7 @@ const DateMenuButton = new Lang.Class({
this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed',
Lang.bind(this, function(calendar, date) {
this._eventList.setDate(date);
this._messageList.setDate(date);
}));
// Whenever the menu is opened, select today
@ -117,8 +117,8 @@ const DateMenuButton = new Lang.Class({
}));
// Fill up the first column
this._eventList = new Calendar.EventsList();
hbox.add(this._eventList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
this._messageList = new Calendar.MessageList();
hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
// Fill up the second column
vbox = new St.BoxLayout({ style_class: 'datemenu-calendar-column',
@ -165,7 +165,7 @@ const DateMenuButton = new Lang.Class({
(this._getCalendarApp() != null);
this._openClocksItem.actor.visible = visible &&
(this._getClockApp() != null);
this._eventList.actor.visible = visible;
this._messageList.actor.visible = visible;
},
_getEventSource: function() {
@ -177,7 +177,7 @@ const DateMenuButton = new Lang.Class({
this._eventSource.destroy();
this._calendar.setEventSource(eventSource);
this._eventList.setEventSource(eventSource);
this._messageList.setEventSource(eventSource);
this._eventSource = eventSource;
this._eventSource.connect('notify::has-calendars', Lang.bind(this, function() {