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:
parent
c7fb65c78e
commit
719d793e22
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user