Calendar: refactor the layout of the event list

In order to have event descriptions on multiple lines, but still
maintain proper alignment with the day and time strings, refactor
the whole event list to be one big table. Headers are implemented
as spanning cells, and uneven spacing is a mix of row/column spacing
and cell padding.

https://bugzilla.gnome.org/show_bug.cgi?id=701231
This commit is contained in:
Giovanni Campagna 2013-06-08 18:31:30 +02:00
parent c7fb65c78e
commit 719d793e22
3 changed files with 84 additions and 74 deletions

View File

@ -1154,9 +1154,9 @@ StScrollBar StButton#vhandle:active {
/* Calendar popup */ /* Calendar popup */
#calendarEventsArea { #calendarArea {
/* this is the width of the second column of the popup */ /* this is the total width of the popup */
min-width: 320px; width: 720px;
} }
.calendar-vertical-separator { .calendar-vertical-separator {
@ -1295,32 +1295,40 @@ StScrollBar StButton#vhandle:active {
color: #333333; color: #333333;
} }
.events-header-vbox { .events-table {
spacing: 6pt; min-width: 320px;
padding-right: .5em; spacing-columns: 6pt;
padding: 0 1.4em;
} }
.events-header-vbox:rtl { .events-table:ltr {
padding-left: .5em; padding-right: 1.9em;
} }
.events-header-hbox { .events-table:rtl {
padding: 0.3em 1.4em; padding-left: 1.9em;
} }
.events-day-header { .events-day-header {
font-weight: bold; font-weight: bold;
color: #999999; color: #999999;
padding: 0.4em 1.4em 0em 1.4em; padding-left: 0.4em;
padding-top: 1.2em;
}
.events-day-header:first-child {
padding-top: 0;
} }
.events-day-header:rtl { .events-day-header:rtl {
padding: 0em 1.4em 0.4em 1.4em; padding-left: 0;
padding-right: 0.4em;
} }
.events-day-dayname { .events-day-dayname {
color: rgba(153, 153, 153, 1.0); color: rgba(153, 153, 153, 1.0);
text-align: left; text-align: left;
min-width: 20px;
} }
.events-day-dayname:rtl { .events-day-dayname:rtl {
@ -1338,23 +1346,12 @@ StScrollBar StButton#vhandle:active {
.events-day-task { .events-day-task {
color: rgba(153, 153, 153, 1.0); color: rgba(153, 153, 153, 1.0);
padding-left: 8pt;
} }
.events-day-name-box { .events-day-task:rtl {
min-width: 15pt; padding-left: 0px;
} padding-right: 8pt;
.events-time-box {
min-width: 48pt;
padding-right: 12pt;
}
.events-time-box:rtl {
padding-right: 0px;
padding-left: 12pt;
}
.events-event-box {
} }
.url-highlighter { .url-highlighter {

View File

@ -675,7 +675,7 @@ const EventsList = new Lang.Class({
Name: 'EventsList', Name: 'EventsList',
_init: function() { _init: function() {
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'}); this.actor = new St.Table({ style_class: 'events-table' });
this._date = new Date(); this._date = new Date();
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', Lang.bind(this, this._update)); this._desktopSettings.connect('changed', Lang.bind(this, this._update));
@ -687,55 +687,72 @@ const EventsList = new Lang.Class({
this._eventSource.connect('changed', Lang.bind(this, this._update)); this._eventSource.connect('changed', Lang.bind(this, this._update));
}, },
_addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) { _addEvent: function(event, index, includeDayName) {
if (includeDayName) { let dayString;
dayNameBox.add(new St.Label( { style_class: 'events-day-dayname', if (includeDayName)
text: day } ), dayString = _getEventDayAbbreviation(event.date.getDay());
{ x_fill: true } ); else
} dayString = '';
timeBox.add(new St.Label( { style_class: 'events-day-time',
text: time} ), let dayLabel = new St.Label({ style_class: 'events-day-dayname',
{ x_fill: true } ); text: dayString });
eventTitleBox.add(new St.Label( { style_class: 'events-day-task', dayLabel.clutter_text.line_wrap = false;
text: desc} )); dayLabel.clutter_text.ellipsize = false;
this.actor.add(dayLabel, { row: index, col: 0,
x_expand: false, x_align: St.Align.END,
y_fill: false, y_align: St.Align.START });
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
let timeString = _formatEventTime(event, clockFormat);
let timeLabel = new St.Label({ style_class: 'events-day-time',
text: timeString });
timeLabel.clutter_text.line_wrap = false;
timeLabel.clutter_text.ellipsize = false;
this.actor.add(timeLabel, { row: index, col: 1,
x_expand: false, x_align: St.Align.MIDDLE,
y_fill: false, y_align: St.Align.START });
let titleLabel = new St.Label({ style_class: 'events-day-task',
text: event.summary });
titleLabel.clutter_text.line_wrap = true;
titleLabel.clutter_text.ellipsize = false;
this.actor.add(titleLabel, { row: index, col: 2,
x_expand: true, x_align: St.Align.START,
y_fill: false, y_align: St.Align.START });
}, },
_addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) { _addPeriod: function(header, index, begin, end, includeDayName, showNothingScheduled) {
let events = this._eventSource.getEvents(begin, end); let events = this._eventSource.getEvents(begin, end);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
if (events.length == 0 && !showNothingScheduled) if (events.length == 0 && !showNothingScheduled)
return; return index;
let vbox = new St.BoxLayout( {vertical: true} ); this.actor.add(new St.Label({ style_class: 'events-day-header', text: header }),
this.actor.add(vbox); { row: index, col: 0, col_span: 3,
// In theory, x_expand should be true here, but x_expand
vbox.add(new St.Label({ style_class: 'events-day-header', text: header })); // is a property of the column for StTable, ie all day cells
let box = new St.BoxLayout({style_class: 'events-header-hbox'}); // get it too
let dayNameBox = new St.BoxLayout({ vertical: true, style_class: 'events-day-name-box' }); x_expand: false, x_align: St.Align.START,
let timeBox = new St.BoxLayout({ vertical: true, style_class: 'events-time-box' }); y_fill: false, y_align: St.Align.START });
let eventTitleBox = new St.BoxLayout({ vertical: true, style_class: 'events-event-box' }); index++;
box.add(dayNameBox, {x_fill: false});
box.add(timeBox, {x_fill: false});
box.add(eventTitleBox, {expand: true});
vbox.add(box);
for (let n = 0; n < events.length; n++) { for (let n = 0; n < events.length; n++) {
let event = events[n]; this._addEvent(events[n], index, includeDayName);
let dayString = _getEventDayAbbreviation(event.date.getDay()); index++;
let timeString = _formatEventTime(event, clockFormat);
let summaryString = event.summary;
this._addEvent(dayNameBox, timeBox, eventTitleBox, includeDayName, dayString, timeString, summaryString);
} }
if (events.length == 0 && showNothingScheduled) { if (events.length == 0 && showNothingScheduled) {
let now = new Date(); let now = new Date();
/* Translators: Text to show if there are no events */ /* Translators: Text to show if there are no events */
let nothingEvent = new CalendarEvent(now, now, _("Nothing Scheduled"), true); let nothingEvent = new CalendarEvent(now, now, _("Nothing Scheduled"), true);
let timeString = _formatEventTime(nothingEvent, clockFormat); this._addEvent(nothingEvent, index, false);
this._addEvent(dayNameBox, timeBox, eventTitleBox, false, "", timeString, nothingEvent.summary); index++;
} }
return index;
}, },
_showOtherDay: function(day) { _showOtherDay: function(day) {
@ -752,20 +769,21 @@ const EventsList = new Lang.Class({
else else
/* Translators: Shown on calendar heading when selected day occurs on different year */ /* Translators: Shown on calendar heading when selected day occurs on different year */
dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d, %Y")); dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d, %Y"));
this._addPeriod(dayString, dayBegin, dayEnd, false, true); this._addPeriod(dayString, 0, dayBegin, dayEnd, false, true);
}, },
_showToday: function() { _showToday: function() {
this.actor.destroy_all_children(); this.actor.destroy_all_children();
let index = 0;
let now = new Date(); let now = new Date();
let dayBegin = _getBeginningOfDay(now); let dayBegin = _getBeginningOfDay(now);
let dayEnd = _getEndOfDay(now); let dayEnd = _getEndOfDay(now);
this._addPeriod(_("Today"), dayBegin, dayEnd, false, true); index = this._addPeriod(_("Today"), index, dayBegin, dayEnd, false, true);
let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000); let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000);
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000); let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true); index = this._addPeriod(_("Tomorrow"), index, tomorrowBegin, tomorrowEnd, false, true);
let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7; let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7;
@ -776,7 +794,7 @@ const EventsList = new Lang.Class({
*/ */
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000); let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000); let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000);
this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false); index = this._addPeriod(_("This week"), index, thisWeekBegin, thisWeekEnd, true, false);
} else { } else {
/* otherwise it's one of the two last days of the week ... show /* otherwise it's one of the two last days of the week ... show
* "Next week" and include events up until and including *next* * "Next week" and include events up until and including *next*
@ -784,7 +802,7 @@ const EventsList = new Lang.Class({
*/ */
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000); let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000); let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000);
this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false); index = this._addPeriod(_("Next week"), index, nextWeekBegin, nextWeekEnd, true, false);
} }
}, },

View File

@ -80,7 +80,7 @@ const DateMenuButton = new Lang.Class({
vbox.add(this._calendar.actor); vbox.add(this._calendar.actor);
let separator = new PopupMenu.PopupSeparatorMenuItem(); let separator = new PopupMenu.PopupSeparatorMenuItem();
vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false}); vbox.add(separator.actor, { y_align: St.Align.END, expand: true, y_fill: false });
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar")); this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate)); this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
@ -106,12 +106,7 @@ const DateMenuButton = new Lang.Class({
hbox.add(this._separator); hbox.add(this._separator);
// Fill up the second column // Fill up the second column
vbox = new St.BoxLayout({ name: 'calendarEventsArea', hbox.add(this._eventList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
vertical: true });
hbox.add(vbox, { expand: true });
// Event list
vbox.add(this._eventList.actor, { expand: true });
// Whenever the menu is opened, select today // Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) { this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {