[gnome-shell/datetime] Start implementing the Date and Time mockups
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/datetime] Start implementing the Date and Time mockups
- Date: Wed, 13 Oct 2010 21:58:40 +0000 (UTC)
commit 85ec4d86f3f8acba5c77b02ac9e4bb9c42d37f5e
Author: David Zeuthen <davidz redhat com>
Date: Wed Oct 13 17:36:52 2010 -0400
Start implementing the Date and Time mockups
data/clock-preferences.ui | 50 +++++++++++-
data/theme/gnome-shell.css | 62 +++++++++++---
js/Makefile.am | 1 +
js/prefs/clockPreferences.js | 13 +++
js/ui/calendar.js | 104 ++++++++++++++++++------
js/ui/dateMenu.js | 189 ++++++++++++++++++++++++++++++++++++++++++
js/ui/main.js | 2 +-
js/ui/panel.js | 18 +---
8 files changed, 386 insertions(+), 53 deletions(-)
---
diff --git a/data/clock-preferences.ui b/data/clock-preferences.ui
index 2e22d9a..68e60ce 100644
--- a/data/clock-preferences.ui
+++ b/data/clock-preferences.ui
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<interface domain="gnome-shell">
+<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="prefs-dialog">
@@ -145,6 +145,54 @@
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="week_check">
+ <property name="label" translatable="yes">Show _week numbers</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label_display1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Calendar</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="padding">6</property>
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index c14709c..ab73548 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -795,6 +795,14 @@ StTooltip {
/* Calendar popup */
+.calendar-vertical-separator {
+ -gradient-width: 2px;
+ -gradient-start: rgba(8,8,8,0);
+ -gradient-end: #333333;
+ -margin-vertical: 1.5em;
+ width: 1em;
+}
+
#calendarPopup {
border-radius: 5px;
background: rgba(0,0,0,0.9);
@@ -807,37 +815,69 @@ StTooltip {
}
.calendar {
- spacing-rows: 5px;
- spacing-columns: 3px;
+ spacing-rows: 0px;
+ spacing-columns: 0px;
}
.calendar-change-month {
+ color: #666666;
+ font-size: 10px;
padding: 2px;
}
.calendar-change-month:hover {
- background: #314a6c;
+ background: #999999;
border-radius: 5px;
}
.calendar-change-month:active {
- background: #213050;
+ background: #aaaaaa;
border-radius: 5px;
}
+.datemenu-date-label {
+ font-size: 16px;
+ font-weight: bold;
+ color: #999999;
+}
+
+.calendar-day-base {
+ font-size: 10px;
+ padding: 5px 3px;
+ text-align: center;
+}
+
+.calendar-day-heading {
+ color: #666666;
+}
+
+.calendar-week-number {
+ color: #666666;
+ font-weight: bold;
+}
+
.calendar-day {
- padding: 1px 2px;
+ border: 1px solid #333333;
+ color: #cccccc;
+}
+
+.calendar-work-day {
+}
+
+.calendar-nonwork-day {
+ background: #181818;
}
.calendar-today {
+ color: #ffffff;
font-weight: bold;
- background: #ffffff;
- color: black;
- border-radius: 5px;
+ background-gradient-direction: vertical;
+ background-gradient-start: #3c3c3c;
+ background-gradient-end: #131313;
}
.calendar-other-month-day {
- color: #cccccc;
+ color: #333333;
}
/* Message Tray */
@@ -988,10 +1028,6 @@ StTooltip {
padding-left: 4px;
}
-.calendar-calendarweek {
- color: #666666;
-}
-
/* App Switcher */
#altTabPopup {
padding: 8px;
diff --git a/js/Makefile.am b/js/Makefile.am
index f35026e..199321c 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -17,6 +17,7 @@ nobase_dist_js_DATA = \
ui/calendar.js \
ui/chrome.js \
ui/dash.js \
+ ui/dateMenu.js \
ui/dnd.js \
ui/docDisplay.js \
ui/environment.js \
diff --git a/js/prefs/clockPreferences.js b/js/prefs/clockPreferences.js
index f35d8e2..866fc30 100644
--- a/js/prefs/clockPreferences.js
+++ b/js/prefs/clockPreferences.js
@@ -13,6 +13,7 @@ const FORMAT_KEY = 'format';
const SHOW_DATE_KEY = 'show-date';
const SHOW_SECONDS_KEY = 'show-seconds';
+const SHOW_WEEKDATE_KEY = 'show-weekdate';
function ClockPreferences(uiFile) {
this._init(uiFile);
@@ -30,6 +31,7 @@ ClockPreferences.prototype = {
this._24hrRadio = builder.get_object('24hr_radio');
this._dateCheck = builder.get_object('date_check');
this._secondsCheck = builder.get_object('seconds_check');
+ this._weekCheck = builder.get_object('week_check');
delete builder;
@@ -37,6 +39,10 @@ ClockPreferences.prototype = {
this._notifyId = this._settings.connect('changed',
Lang.bind(this,
this._updateDialog));
+ this._calendar_settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
+ this._calendar_notifyId = this._calendar_settings.connect('changed',
+ Lang.bind(this,
+ this._updateDialog));
this._12hrRadio.connect('toggled', Lang.bind(this,
function() {
@@ -53,6 +59,11 @@ ClockPreferences.prototype = {
this._settings.set_boolean(SHOW_SECONDS_KEY,
this._secondsCheck.active);
}));
+ this._weekCheck.connect('toggled', Lang.bind(this,
+ function() {
+ this._calendar_settings.set_boolean(SHOW_WEEKDATE_KEY,
+ this._weekCheck.active);
+ }));
this._updateDialog();
},
@@ -68,11 +79,13 @@ ClockPreferences.prototype = {
this._dateCheck.active = this._settings.get_boolean(SHOW_DATE_KEY);
this._secondsCheck.active = this._settings.get_boolean(SHOW_SECONDS_KEY);
+ this._weekCheck.active = this._calendar_settings.get_boolean(SHOW_WEEKDATE_KEY);
},
_onResponse: function() {
this._dialog.destroy();
this._settings.disconnect(this._notifyId);
+ this._calendar_settings.disconnect(this._calendar_notifyId);
this.emit('destroy');
}
};
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index 078c69d..1ead975 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -6,6 +6,8 @@ const Lang = imports.lang;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const Gettext_gtk20 = imports.gettext.domain('gtk20');
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const WEEKDATE_HEADER_WIDTH_DIGITS = 3;
@@ -17,6 +19,14 @@ function _sameDay(dateA, dateB) {
dateA.getYear() == dateB.getYear());
}
+/* TODO: maybe needs config - right now we assume that Saturday and
+ * Sunday are work days (not true in e.g. Israel, it's Sunday and
+ * Monday there)
+ */
+function _isWorkDay(date) {
+ return date.getDay() != 0 && date.getDay() != 6;
+}
+
function _getCalendarWeekForDate(date) {
// Based on the algorithms found here:
// http://en.wikipedia.org/wiki/Talk:ISO_week_date
@@ -43,6 +53,50 @@ function _getDigitWidth(actor){
return width;
}
+function _getCustomDayAbrreviation(day_number) {
+ let ret;
+ switch (day_number) {
+ case 0:
+ /* Translators: One-letter abbreaviation for Sunday - note:
+ * all one-letter abbreviations are always shown together and
+ * in order, e.g. "S M T W T F S"
+ */
+ ret = _("S");
+ break;
+
+ case 1:
+ /* Translators: One-letter abbreaviation for Monday */
+ ret = _("M");
+ break;
+
+ case 2:
+ /* Translators: One-letter abbreaviation for Tuesday */
+ ret = _("T");
+ break;
+
+ case 3:
+ /* Translators: One-letter abbreaviation for Wednesday */
+ ret = _("W");
+ break;
+
+ case 4:
+ /* Translators: One-letter abbreaviation for Thursday */
+ ret = _("T");
+ break;
+
+ case 5:
+ /* Translators: One-letter abbreaviation for Friday */
+ ret = _("F");
+ break;
+
+ case 6:
+ /* Translators: One-letter abbreaviation for Saturday */
+ ret = _("S");
+ break;
+ }
+ return ret;
+}
+
function Calendar() {
this._init();
}
@@ -125,36 +179,32 @@ Calendar.prototype = {
this._topBox.add(back);
back.connect('clicked', Lang.bind(this, this._prevMonth));
- this._dateLabel = new St.Label();
+ this._dateLabel = new St.Label({style_class: 'calendar-change-month'});
this._topBox.add(this._dateLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' });
this._topBox.add(forward);
forward.connect('clicked', Lang.bind(this, this._nextMonth));
+ // Add weekday labels...
+ //
// We need to figure out the abbreviated localized names for the days of the week;
// we do this by just getting the next 7 days starting from right now and then putting
// them in the right cell in the table. It doesn't matter if we add them in order
+ //
let iter = new Date(this.date);
iter.setSeconds(0); // Leap second protection. Hah!
iter.setHours(12);
-
- if (this._useWeekdate) {
- this._weekdateHeader = new St.Label();
- this.actor.add(this._weekdateHeader,
- { row: 1,
- col: 0,
- x_fill: false, x_align: St.Align.MIDDLE });
- this._setWeekdateHeaderWidth();
- } else {
- this._weekdateHeader = null;
- }
-
for (let i = 0; i < 7; i++) {
- this.actor.add(new St.Label({ text: iter.toLocaleFormat('%a') }),
+ // Could use iter.toLocaleFormat('%a') but that normally gives three characters
+ // and we want, ideally, a single character for e.g. S M T W T F S
+ let custom_day_abbrev = _getCustomDayAbrreviation(iter.getDay());
+ let label = new St.Label({ text: custom_day_abbrev });
+ label.style_class = 'calendar-day-base calendar-day-heading';
+ this.actor.add(label,
{ row: 1,
col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
- x_fill: false, x_align: St.Align.END });
+ x_fill: false, x_align: St.Align.MIDDLE });
iter.setTime(iter.getTime() + MSECS_IN_DAY);
}
@@ -234,24 +284,30 @@ Calendar.prototype = {
let row = 2;
while (true) {
let label = new St.Label({ text: iter.getDate().toString() });
+ let style_class;
+
+ style_class = 'calendar-day-base calendar-day';
+ if (_isWorkDay(iter))
+ style_class += ' calendar-work-day'
+ else
+ style_class += ' calendar-nonwork-day'
+
if (_sameDay(now, iter))
- label.style_class = 'calendar-day calendar-today';
+ style_class += ' calendar-today';
else if (iter.getMonth() != this.date.getMonth())
- label.style_class = 'calendar-day calendar-other-month-day';
- else
- label.style_class = 'calendar-day';
+ style_class += ' calendar-other-month-day';
+
+ label.style_class = style_class;
let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.add(label,
- { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
- x_fill: false, x_align: St.Align.END });
+ { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 });
if (this._useWeekdate && iter.getDay() == 4) {
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
- style_class: 'calendar-day calendar-calendarweek'});
+ style_class: 'calendar-day-base calendar-week-number'});
this.actor.add(label,
- { row: row, col: 0,
- x_fill: false, x_align: St.Align.MIDDLE });
+ { row: row, col: 0, y_align: St.Align.MIDDLE });
}
iter.setTime(iter.getTime() + MSECS_IN_DAY);
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
new file mode 100644
index 0000000..77d7bba
--- /dev/null
+++ b/js/ui/dateMenu.js
@@ -0,0 +1,189 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Cairo = imports.cairo;
+const Clutter = imports.gi.Clutter;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const Main = imports.ui.main;
+const PanelMenu = imports.ui.panelMenu;
+const PopupMenu = imports.ui.popupMenu;
+const Calendar = imports.ui.calendar;
+
+const CLOCK_FORMAT_KEY = 'format';
+const CLOCK_CUSTOM_FORMAT_KEY = 'custom-format';
+const CLOCK_SHOW_DATE_KEY = 'show-date';
+const CLOCK_SHOW_SECONDS_KEY = 'show-seconds';
+
+function DateMenuButton() {
+ this._init();
+}
+
+function on_vert_sep_repaint (area)
+{
+ let cr = area.get_context();
+ let themeNode = area.get_theme_node();
+ let [width, height] = area.get_surface_size();
+ let found, margin, gradientHeight;
+ [found, margin] = themeNode.get_length('-margin-vertical', false);
+ [found, gradientWidth] = themeNode.get_length('-gradient-width', false);
+ let startColor = new Clutter.Color();
+ themeNode.get_color('-gradient-start', false, startColor);
+ let endColor = new Clutter.Color();
+ themeNode.get_color('-gradient-end', false, endColor);
+
+ let gradientHeight = (height - margin * 2);
+ let gradientOffset = (width - gradientWidth) / 2;
+ let pattern = new Cairo.LinearGradient(gradientOffset, margin, gradientOffset + gradientWidth, height - margin);
+ pattern.addColorStopRGBA(0, startColor.red / 255, startColor.green / 255, startColor.blue / 255, startColor.alpha / 255);
+ pattern.addColorStopRGBA(0.5, endColor.red / 255, endColor.green / 255, endColor.blue / 255, endColor.alpha / 255);
+ pattern.addColorStopRGBA(1, startColor.red / 255, startColor.green / 255, startColor.blue / 255, startColor.alpha / 255);
+ cr.setSource(pattern);
+ cr.rectangle(gradientOffset, margin, gradientWidth, gradientHeight);
+ cr.fill();
+};
+
+DateMenuButton.prototype = {
+ __proto__: PanelMenu.Button.prototype,
+
+ _init: function() {
+ let item;
+
+ PanelMenu.Button.prototype._init.call(this, St.Align.START);
+
+ this._clock = new St.Label();
+ this.actor.set_child(this._clock);
+
+ this._date = new St.Label();
+ this._date.style_class = 'datemenu-date-label';
+ this.menu._box.add(this._date);
+
+ this._calendar = new Calendar.Calendar();
+ this.menu._box.add(this._calendar.actor);
+
+ item = new PopupMenu.PopupSeparatorMenuItem();
+ this.menu.addMenuItem(item);
+
+ item = new PopupMenu.PopupImageMenuItem(_("Date and Time Settings"), 'gnome-shell-clock-preferences');
+ item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
+ this.menu.addMenuItem(item);
+
+ this._clockSettings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
+ this._clockSettings.connect('changed', Lang.bind(this, this._clockSettingsChanged));
+
+ this._vertSep = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
+ pseudo_class: 'highlighted' });
+ //this._vertSep.set_width (25);
+ this._vertSep.connect('repaint', Lang.bind(this, on_vert_sep_repaint));
+
+ let hbox;
+ let orig_menu_box;
+ orig_menu_box = this.menu._box;
+ this.menu._boxPointer.bin.remove_actor(orig_menu_box);
+ hbox = new St.BoxLayout();
+ hbox.add(orig_menu_box);
+ hbox.add(this._vertSep);
+ hbox.add(new St.Label({text: "foo0"}));
+ this.menu._boxPointer.bin.set_child(hbox);
+ this.menu._box = hbox;
+
+ // Start the clock
+ this._updateClockAndDate();
+ },
+
+ _clockSettingsChanged: function() {
+ this._updateClockAndDate();
+ },
+
+ _updateClockAndDate: function() {
+ let format = this._clockSettings.get_string(CLOCK_FORMAT_KEY);
+ let showDate = this._clockSettings.get_boolean(CLOCK_SHOW_DATE_KEY);
+ let showSeconds = this._clockSettings.get_boolean(CLOCK_SHOW_SECONDS_KEY);
+
+ let clockFormat;
+ let dateFormat;
+
+ switch (format) {
+ case 'unix':
+ // force updates every second
+ showSeconds = true;
+ clockFormat = '%s';
+ break;
+ case 'custom':
+ // force updates every second
+ showSeconds = true;
+ clockFormat = this._clockSettings.get_string(CLOCK_CUSTOM_FORMAT_KEY);
+ break;
+ case '24-hour':
+ if (showDate)
+ /* Translators: This is the time format with date used
+ in 24-hour mode. */
+ clockFormat = showSeconds ? _("%a %b %e, %R:%S")
+ : _("%a %b %e, %R");
+ else
+ /* Translators: This is the time format without date used
+ in 24-hour mode. */
+ clockFormat = showSeconds ? _("%a %R:%S")
+ : _("%a %R");
+ break;
+ case '12-hour':
+ default:
+ if (showDate)
+ /* Translators: This is a time format with date used
+ for AM/PM. */
+ clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
+ : _("%a %b %e, %l:%M %p");
+ else
+ /* Translators: This is a time format without date used
+ for AM/PM. */
+ clockFormat = showSeconds ? _("%a %l:%M:%S %p")
+ : _("%a %l:%M %p");
+ break;
+ }
+
+ let displayDate = new Date();
+ let msecRemaining;
+ if (showSeconds) {
+ msecRemaining = 1000 - displayDate.getMilliseconds();
+ if (msecRemaining < 50) {
+ displayDate.setSeconds(displayDate.getSeconds() + 1);
+ msecRemaining += 1000;
+ }
+ } else {
+ msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
+ displayDate.getMilliseconds());
+ if (msecRemaining < 500) {
+ displayDate.setMinutes(displayDate.getMinutes() + 1);
+ msecRemaining += 60000;
+ }
+ }
+
+ this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
+
+ /* Translators: This is the date format to use */
+ dateFormat = _("%B %e, %Y");
+ this._date.set_text(displayDate.toLocaleFormat(dateFormat));
+
+ Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClockAndDate));
+ return false;
+ },
+
+ _onPreferencesActivate: function() {
+ Main.overview.hide();
+ this._spawn(['gnome-shell-clock-preferences']);
+ },
+
+ _spawn: function(args) {
+ // FIXME: once Shell.Process gets support for signalling
+ // errors we should pop up an error dialog or something here
+ // on failure
+ let p = new Shell.Process({'args' : args});
+ p.run();
+ }
+};
diff --git a/js/ui/main.js b/js/ui/main.js
index a0287c3..cdab69c 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -247,7 +247,7 @@ function _relayout() {
// will be updated when it is next shown. We do the same for
// the calendar popdown.
overview.hide();
- panel.hideCalendar();
+ //panel.hideCalendar();
}
// metacity-clutter currently uses the same prefs as plain metacity,
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 26c3a03..4abbcf2 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -16,6 +16,7 @@ const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const StatusMenu = imports.ui.statusMenu;
+const DateMenu = imports.ui.dateMenu;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@@ -34,11 +35,6 @@ const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator
};
-const CLOCK_FORMAT_KEY = 'format';
-const CLOCK_CUSTOM_FORMAT_KEY = 'custom-format';
-const CLOCK_SHOW_DATE_KEY = 'show-date';
-const CLOCK_SHOW_SECONDS_KEY = 'show-seconds';
-
function AnimatedIcon(name, size) {
this._init(name, size);
}
@@ -792,11 +788,9 @@ Panel.prototype = {
this._menus.addMenu(appMenuButton.menu);
/* center */
-
- this._clockButton = new ClockButton();
- this._centerBox.add(this._clockButton.actor, { y_fill: true });
-
- this._menus.addMenu(this._clockButton.menu);
+ this._dateMenu = new DateMenu.DateMenuButton();
+ this._centerBox.add(this._dateMenu.actor, { y_fill: true });
+ this._menus.addMenu(this._dateMenu.menu);
/* right */
@@ -856,10 +850,6 @@ Panel.prototype = {
Main.chrome.addActor(this.actor, { visibleInOverview: true });
},
- hideCalendar: function() {
- this._clockButton.closeCalendar();
- },
-
startupAnimation: function() {
this.actor.y = -this.actor.height;
Tweener.addTween(this.actor,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]