Raspberry swirl cheesecake cupcakes

I volunteered to bring some baked goodies for a rowing event earlier this year, and for some reason I decided that I would really like to bring something that looks nice. Some bits of Googling later, I came across a lovely recipe for cheesecake cupcakes with raspberry swirls at Annie’s Eats. These not only look amazing: they taste amazing. You get all the joys of cheesecake in a nice, manageable quantity. And cupcakes are much easier to make than ordinary (big) cheesecake. In short: make this recipe.

Aren't they adorable?
Aren’t they adorable?

Cheesecake is quite forgiving, as long as you’re gentle with it. I didn’t need as much cheesecake as the original recipe, and I found it was a little tricky to find cream cheese in the particular quantity I needed, so I modified the original recipe for my purposes. A few weekends ago I did it again with the same tweaks and it worked out wonderfully, so I thought I would share.

My recipe makes about two thirds of the original, so it will give you a little over two dozen cupcakes. I added some cottage cheese, and I’m using “medium” cupcake cups, which are 2.5″ in diameter at the top and a little under 1″ tall.

Those extra raspberries in the photo provide scale, and deliciousness. I don’t mention them in the recipe, but I’m sure you know what to do. I’m sticking with the raspberry swirl here, but I should mention it’s really easy to make a few different toppings and mix them in as well. I’ve listed some I have tried at the bottom.

Fair warning: I am not an experienced chef, which is why my website is about software and not cooking. But, hey, it worked for me! (And of course, the recipe at Annie’s Eats is bound to work perfectly. It’s tried and tested and very well photographed).

Ingredients

For the crust

  • 1 ½ cups graham cracker crumbs
  • 4 tbsp unsalted butter, melted
  • 3 tbsp sugar

For the filling

  • 500 grams reduced fat cream cheese, at room temperature (use blocks of cream cheese if you can)
  • 100 grams cottage cheese (try to squish it a little and drain some of the liquid)
  • 1 cup sugar
  • pinch of salt
  • ⅔ tsp vanilla extract
  • 3 large eggs, at room temperature

For the raspberry swirl

  • ¾ cup raspberries (fresh or frozen)
  • 2 tbsp sugar

Directions

  1. Preheat the oven to bake at 325° F, and line some muffin tins with cupcake liners. If you have a lot of empty spaces in the tin, fill one of those spaces with a bit of water. You may need to come back to this step a few times (depending on how many muffin tins you have), and that’s okay.
  2. In a large bowl, stir together the graham cracker crumbs, 3 tbsp sugar and melted butter until they are well combined and moistened.
  3. Press up to 1 tbsp graham cracker filling into each cupcake liner, and push it down. This isn’t exact, of course, but your crust should be even, and about 5 mm thick. Bake these until the crust is set – about 5 minutes – then set aside to cool. Leave the cupcake liners, with the crusts, in the tin: you’ll be using it again very soon.
  4. Meanwhile, put the raspberries in a blender, and blend until they are smooth. Run the purée through a fine strainer to remove the seeds, then stir in the 2 tbsp sugar.
  5. Using a stand mixer on medium speed, beat the cream cheese and the cottage cheese until it is light and fluffy. Blend in the 1 cup sugar until the mixture is smooth. Mix in the salt and vanilla. Add the eggs, one at a time, mixing well after each addition. Pour 2-3 tbsp of the cheesecake filling into each cupcake liner, on top of the graham cracker crust. (You might want to add a little more or less depending on your cupcake liners. Keep an eye on them in the oven and you’ll be fine).
  6. For each cupcake, dot ⅓ tsp of the raspberry purée in a few dots on top of the cheesecake filling. Then, using a toothpick or a chopstick, swirl the purée to create a marbled effect.
  7. Bake the cupcakes until the filling is set; about 22 minutes. Transfer them to a cooling rack until they have cooled to room temperature, then transfer them to the refrigerator for 4 hours. The cupcakes will be quite puffy when you remove them from the oven, but they’ll settle back down once they have cooled. Be extra careful with them until that happens, though.
    • Now is a good time to plop on some decorations, if you were planning to. Once your cupcakes have settled a little, lightly push a fresh raspberry onto each one, or maybe sprinkle some chocolate flakes on top. You can do that later, too, but once the cupcakes cool you’ll need to find other means to make things stick.

Just try not to eat them all yourself, and you’re done. Good luck!


Some extra toppings you could try…

The original recipe calls for raspberry swirls, and that works beautifully. But you might like to try something else, too. Chocolate sauce and blueberry sauce have worked well for me. It’s hard to be exact, so be prepared for some leftovers. Careful, though: the raspberry purée is quite light, but the others aren’t always like that. If your topping seems to sink into the cheesecake filling, make sure you spread it out lightly. If you leave a particularly heavy dot, it could punch a hole in your cupcake.

I was meaning to try orange sauce, too. If you do, I’d love to know how it goes.

Blueberry

  • 1 cup blueberries (fresh or frozen)
  • 2 tbsp sugar
  • ½ tbsp cornstarch
  • ½ tbsp lemon juice

Combine all the ingredients in a saucepan and cook over low heat, mashing the blueberries slightly, for about five minutes. Once the sauce has reduced and slightly thickened, remove it from the heat and allow it to cool slightly. Use just the liquid part with your cheesecake. You can save the blueberry bits to sprinkle over the cupcakes. Or you can eat them, because blueberries are delicious.

Chocolate

This sauce is quite thick, so you won't need very much
The chocolate sauce is quite thick, so you won’t need very much
  • ⅔ cup cocoa
  • 1 ½ cup white sugar
  • 1 ⅓ cup water
  • 1 tsp vanilla extract

Combine the first three ingredients in a saucepan over medium heat. Bring to a boil and let it boil for 1 minute. Remove from the heat and stir in vanilla. Allow the sauce to cool before adding it to the cheesecake.

The flakes in the photo are from a block of white cooking chocolate and a lemon zester. Just add them when the cupcakes come out of the oven and they should stick nicely.

GNOME Break Timer: Final report

Well, it’s September, so I guess it’s time to call it quits with that whole “summer” thing. This has been a really nice few months. I’m very grateful that I could participate in Google Summer of Code this year with my project to build a shiny new Break Timer application for GNOME 3.

This was meant to be a picture of Fall's first day of torrential wind and rain, but the rain stopped as soon as I went outside and this is all I got. Stupid rain.
This was meant to be a picture of Fall’s first day of torrential wind and rain, but the rain stopped as soon as I went outside and this is all I got. Stupid rain.

So, where am I leaving you? With GNOME Break Timer 1.1, of course! (And I’m not leaving). I think my project over the summer has been successful. At times I have had the unmistakeable feeling that I was trying to spread too little butter over too much bread, but we always found something interesting to work on (including a nifty and GNOMEy side project that I’ll talk about really soon, but mostly on Break Timer itself) and I think we have some good quality code as a result — and a lovely little application, too!

GNOME Break Timer 1.1

Well, it has an About dialog
Well, it has an About dialog

Don’t worry, that icon is a quick placeholder, and I realize it looks confusingly similar to either a normal clock, a speaker or a power button. If you feel strongly about it, I will be eternally grateful if you check out the art request for a new icon.

Here’s what I did this summer, in summary…

  • Cleaned up a lot of old code, fixing bugs and removing oodles of unwanted complexity.
  • Adopted a “normal” build system and fought off my intense fear of Automake. (I now simply dislike Automake. That feels like progress).
  • Made a cute little application to get started with Break Timer, view the current break status, and set a break schedule. I think it’s pretty cool.
  • Improved the activity tracking code so it’ll be way easier to adapt to changes in the input stack. I still need to take a close look at how this will work under Wayland, but I’m less worried, at least.
  • Polished up the “take a break” notifications and added automatic screen locking, as well as better awareness of the system in general.
  • Implemented really awesome state saving between sessions.
  • Investigated per-application defaults for notification appearance. (Didn’t go brilliantly, but I’m going to try again. More on that later).
  • Wrote lots of tests. I didn’t get to write any UI tests, and I was hoping to find out about testing timeouts and timers but I’ll need to save that for another day. Probably a rainy one. Still, it should be very hard for someone to (unknowingly) break any of the more fiddly parts of the application. I’m sure that will pay off in the long run.
  • Learned all about GObject, Vala, Cairo, unit tests, GNOME, and wonderful new things in GTK!
  • And I wrote a blog post for each of those things.

All sorts of people have helped me with my project over the summer. Thanks, Jasper and Allan for being so patient with me :) And thanks, GNOME! You folks are all brilliant. I’m definitely going to keep going with this project and I’m excited to work with you all in the future.

GNOME Break Timer: Week 13

I’m nearing the end of a very busy few weeks, and getting very close to that soft pencils down date! With school starting up again this hasn’t been my most productive week on the GNOME Break Timer front, but I’m pretty happy with what’s been done.

First, most importantly, Jasper and the GNOME admins helped me get to set up on gnome.org’s infrastructure! This is really exciting to me, because hosting and bug tracking looked like a crazy jumble throughout my project, and they got it all sorted out very efficiently. This feels a lot more real now, somehow, and I feel like I’m in a better position to continue maintaining this for a long time.

So, here are the important links:

Incidentally: l10n.gnome.org, you’re awesome. I noticed a bunch of translations committed before I even knew gnome-break-timer was up there, and I was blown away.

What else is new? Unit tests, bits and pieces for maintainability (including code format and documentation), and some visual fun for the status panel.

GNOME Clocks has a really new cool widget for its countdowns and timers. I went ahead and borrowed that design to replace the very boring (and repetitive) icons we had before. I think this helps to quickly get across what’s going on. Also, I’m just a fan of common UI elements.

We show how close a break is like how GNOME Clocks shows a countdown
We show how close a break is like how GNOME Clocks shows a countdown

I also added some arrows, like the ones in Alan’s early mockups. This was all really fun: I hadn’t really explored Cairo before, and I was very impressed with how easy it was to get nice looking curves drawing on the screen. It took a bit of tweaking to get that arrow arranged neatly, without overlapping the text (ever), but I think I got it where I needed. I guess I’ll wait and see if anyone manages to break it.

The arrows probably aren't exactly necessary (I hope), but they add a bit of whimsy that I find quite appealing
The arrows probably aren’t exactly necessary (I hope), but they add a bit of whimsy that I find quite appealing

Over the weekend I’m going to be busy with yet more stuff my past self went and volunteered me for, but I’ll be back soon with some more progress. (Also, I promise one of those distractions is a really awesome charity web project that I’m very excited about. I’ll be able to show it off in the start of November, and I honestly can’t wait). I’m down to “nice to have” features at this point, and the next one is collecting some basic statistics like how many breaks you ignored (or didn’t ignore) last week. Of course, this isn’t so the application can label anyone a bad person. Instead, I’m hoping this will make way for simple, positive and helpful messages in the status dialog. A lot of that could use extra design work, but at least having the data in place will be a nice start – and I’ll certainly be giving it a shot anyway.

Other than that, I’m going to be improving the experience for translators with notes for some of the weirder strings in the application. A few more unit tests, some documentation, a placeholder icon, and a 1.0 release. Hooray!

Since I’ve been working on a lot of cleanup already, and the last few weeks were a bit slow, I’ll be working on code past Monday the 16th’s soft pencils down date (at risk of some panic near the end). Of course, that isn’t terribly important: I look forward to maintaining and improving this well into the future, too.

GNOME Break Timer: Week 10

Earlier, when I mentioned that I was going to work on polish, I was thinking of a rather unfortunate line in my original roadmap that honestly just said “polish.” I started this chunk of my GSoC project with a new list of things I have been putting off for said polish phase, and it turned out to be quite substantial. I have several cool new things this week.

First, I added a simple, custom container widget that allocates space for all of it children – whether or not they are visible – and distributes that space among the visible children. This way, our Break Schedule dialog is always the same shape, even though its contents change. This is sort of like using a GtkStack with the homogeneous property set to true. Once I wrapped my head around size requests and allocations and requisitions, it was really easy to implement. I’m not sure if it’s correct, strictly speaking, but it works for me.

class FixedSizeGrid : Gtk.Grid {
	public FixedSizeGrid() {
		Object();
	}

	public override void adjust_size_request (Gtk.Orientation orientation, ref int minimum_size, ref int natural_size) {
		foreach (Gtk.Widget widget in this.get_hidden_children()) {
			int widget_allocated_size = 0;

			if (orientation == Gtk.Orientation.VERTICAL && this.orientation == Gtk.Orientation.VERTICAL) {
				widget_allocated_size = widget.get_allocated_height();
			} else if (orientation == Gtk.Orientation.HORIZONTAL && this.orientation == Gtk.Orientation.HORIZONTAL) {
				widget_allocated_size = widget.get_allocated_width();
			}

			minimum_size += widget_allocated_size;
			natural_size += widget_allocated_size;

			widget.adjust_size_request(orientation, ref minimum_size, ref natural_size);
		}

		base.adjust_size_request(orientation, ref minimum_size, ref natural_size);
	}

	private List get_hidden_children() {
		var hidden_children = new List();
		foreach (Gtk.Widget widget in this.get_children()) {
			if (! widget.is_visible()) hidden_children.append(widget);
		}
		return hidden_children;
	}
}

The big thing I worked on over the last two weeks was making the break timer service remember its state between sessions. Break Timer will remember if you need to take a break after you log out or restart the computer, and in the future it will be able to keep track of interesting statistics very easily. This also makes it much, much harder to “cheat,” by accident or intentionally, because it will always pick up where it left off.

I decided to store the program’s state in the user’s cache folder using a json file, since we can work with json-glib quite nicely from Vala code. That happens when the process is (cleanly) interrupted or when gnome-session says it’s time to stop. (Thanks to Guilhem Bonnefille on gnome-devel-list for pointing me in the right direction about gnome-session). When the application starts, it reads that cache file and updates all its timers and counters accordingly. The way I implemented this leaves the door wide open for keeping breaks in sync between systems, over the network, which would be really cool.

I ran some finicky problems working on this; I guess I don’t usually have to work with quite as many moving parts. I was very glad that several years of people extolling the virtues of test-driven development (most recently David Cameron’s awesome Quality Assurance course at SFU) finally rubbed off on me: as soon as I wrote a test case for the problem I was working on, it all got way easier. And I got a (slightly clunky) test case for free! I must remember to do more of that.

GNOME Break Timer: Week 8

Seriously regretting my boring choice of titles for these blog posts, but it’s too late to change it now.

Why, hello there! The last two weeks haven’t been the brilliantest for my work on GNOME Break Timer – partly because all my other unrelated projects, which I’ve been mostly ignoring in favour of Break Timer, have suddenly flared up and demanded attention – but I still got some nice stuff done. And I passed my statistics course and almost finished a cool charity website. (More on that soon, I hope?).

Most importantly, I decided that it’s time to add some tests. I added a test folder to the build system, and after bracing myself for a nightmare I was really impressed with how easy it was to get going. Further evidence that my fear of tests is entirely irrational.

With all the GNOME project automake stuff set up, I just needed to build a test runner using GLib’s test framework and list it in the TEST_PROGS variable. make check is figured out all on its own. So, that was lovely!

While everyone was off having fun at GUADEC, I fooled around writing unit tests. Of course, I did run into some trickiness: most of my time was spent making the application more testable (cursing Automake some more, putting everything in noinst_LTLIBRARIES), and fixing bugs that I encountered in the process of writing unit tests. This is all for a good cause, though: I am feeling more and more confident that the bus factor for this project can increase beyond 1.

Of course, I didn’t write unit tests for everything. That would be lovely, but it could also take quite a long time. (Quicker now, of course, since all the kinks have been worked out). Instead, I focused on parts of the application that I have broken by accident in the past: monitoring activity, and triggering breaks. The application uses many global things like system time, as well as timers and timeouts. Those can all be rather troublesome to test, unfortunately, but I found my way around them. I created a custom g_get_real_time function that will either return the actual time or a time set by the test suite, so we can rigorously test how certain objects behave as the time changes.

Most of this is quite boring, but I’m happy with it anyway. I wasn’t thrilled with glib’s syntax for writing a test suite – I’m used to wrapping these things in objects – so I borrowed the TestSuite and TestCase classes from libgee’s test suite, adding some extra twists.

Here is tests.vala, which is used by all of the test runners:

// GLib's TestSuite and TestCase are compact classes, so we wrap them in real GLib.Objects for convenience
// This base code is partly borrowed from libgee's test suite, at https://git.gnome.org/browse/libgee

public abstract class SimpleTestSuite : Object {
	private GLib.TestSuite g_test_suite;
	private Adaptor[] adaptors = new Adaptor[0];

	private class Adaptor {
		private SimpleTestSuite test_suite;
		private SimpleTestCase test;

		public Adaptor(SimpleTestSuite test_suite, owned SimpleTestCase test) {
			this.test_suite = test_suite;
			this.test = (owned)test;
		}

		private string get_short_name() {
			string base_name = this.test_suite.get_name();
			string test_full_name = this.test.get_name();
			if (test_full_name.has_prefix(base_name)) {
				return test_full_name.splice(0, base_name.length);
			} else {
				return test_full_name;
			}
		}

		private void setup(void *fixture) {
			this.test_suite.setup();
		}

		private void run(void *fixture) {
			this.test.run(this.test_suite);
		}

		private void teardown(void *fixture) {
			this.test_suite.teardown();
		}

		public GLib.TestCase get_g_test_case() {
			return new GLib.TestCase(
				this.get_short_name(),
				(TestFixtureFunc)this.setup,
				(TestFixtureFunc)this.run,
				(TestFixtureFunc)this.teardown
			);
		}
	}

	public SimpleTestSuite() {
		var name = this.get_name();
		this.g_test_suite = new GLib.TestSuite(name);
	}

	public void add_to(GLib.TestSuite parent) {
		parent.add_suite(this.g_test_suite);
	}

	public GLib.TestSuite get_g_test_suite() {
		return this.g_test_suite;
	}

	public string get_name() {
		return this.get_type().name();
	}

	public void add_test(owned SimpleTestCase test) {
		var adaptor = new Adaptor(this, (owned)test);
		this.adaptors += adaptor;
		this.g_test_suite.add(adaptor.get_g_test_case());
	}

	public virtual void setup() {
	}

	public virtual void teardown() {
	}
}

public interface SimpleTestCase : Object {
	public abstract void run(T context);

	public void add_to(SimpleTestSuite test_suite) {
		test_suite.add_test(this);
	}

	public string get_name() {
		return this.get_type().name();
	}
}

class TestRunner : Object {
	private GLib.TestSuite root_suite;

	private File tmp_dir;
	const string SCHEMA_FILE_NAME = "org.gnome.break-timer.gschema.xml";

	public TestRunner(ref unowned string[] args, GLib.TestSuite? root_suite = null) {
		GLib.Test.init(ref args);
		if (root_suite == null) {
			this.root_suite = GLib.TestSuite.get_root();
		} else {
			this.root_suite = root_suite;
		}
	}

	public void add(SimpleTestSuite suite) {
		suite.add_to(this.root_suite);
	}

	public virtual void global_setup() {
		try {
			var tmp_path = DirUtils.make_tmp("gnome-break-timer-test-XXXXXX");
			tmp_dir = File.new_for_path(tmp_path);
		} catch (Error e) {
			GLib.warning("Error creating temporary directory for test files: %s".printf(e.message));
		}

		string target_data_path = Path.build_filename(tmp_dir.get_path(), "share");
		string target_schema_path = Path.build_filename(tmp_dir.get_path(), "share", "glib-2.0", "schemas");

		Environment.set_variable("GSETTINGS_BACKEND", "memory", true);

		var original_data_dirs = Environment.get_variable("XDG_DATA_DIRS");
		Environment.set_variable("XDG_DATA_DIRS", "%s:%s".printf(target_data_path, original_data_dirs), true);

		File source_schema_file = File.new_for_path(
			Path.build_filename(get_top_builddir(), "data", SCHEMA_FILE_NAME)
		);

		File target_schema_dir = File.new_for_path(target_schema_path);
		try {
			target_schema_dir.make_directory_with_parents();
		} catch (Error e) {
			GLib.warning("Error creating directory for schema files: %s", e.message);
		}

		File target_schema_file = File.new_for_path(
			Path.build_filename(target_schema_dir.get_path(), SCHEMA_FILE_NAME)
		);

		try {
			source_schema_file.copy(target_schema_file, FileCopyFlags.OVERWRITE);
		} catch (Error e) {
			GLib.warning("Error copying schema file: %s", e.message);
		}

		int compile_schemas_result = Posix.system("glib-compile-schemas %s".printf(target_schema_path));
		if (compile_schemas_result != 0) {
			GLib.warning("Could not compile schemas in %s", target_schema_path);
		}
	}

	public virtual void global_teardown() {
		if (tmp_dir != null) {
			var tmp_dir_path = tmp_dir.get_path();
			int delete_tmp_result = Posix.system("rm -rf %s".printf(tmp_dir_path));
			if (delete_tmp_result != 0) {
				GLib.warning("Could not delete temporary files in %s", tmp_dir_path);
			}
		}
	}

	public int run() {
		this.global_setup();
		GLib.Test.run();
		this.global_teardown();
		return 0;
	}

	private static string get_top_builddir() {
		var builddir = Environment.get_variable("top_builddir");
		if (builddir == null) builddir = "..";
		return builddir;
	}
}

And here’s a really simple test suite and test runner:

public class test_Example : SimpleTestSuite {
	public string? foo;

	public test_Example() {
		new test_example_foo_is_bar().add_to(this);
	}

	public override void setup() {
		this.foo = "bar";
	}
}

class test_example_foo_is_bar : Object, SimpleTestCase<test_Example> {
	public void run(test_Example context) {
		assert(context.foo == "bar");
	}
}

public static int main(string[] args) {
	var runner = new TestRunner(ref args);
	runner.add(new test_Example());
	return runner.run();
}

Of course, you might note that this still isn’t thread-safe since we’re passing the same test_Example instance as the parameter for all of our SimpleTestCases, and the syntax is slightly unusual, but I’m quite fond of the extra brevity. One nice bit is this figures out the name of each test based on GObject type information, so we never need to write it explicitly. The test runner ultimately says that a test named “/test_Example/test_example_foo_is_bar” has passed, and it can deal with all sorts of stuff well away from the test code. It’s worked well so far, anyway.

So, that’s about it for the last two weeks. I also submitted an art request for some new icons, and I’m going to try following up on that where I can. This is definitely in the “polish” phase – just with a lot yet to be polished.

GNOME Break Timer: Week 6

It’s time to talk about my GSoC project again, where I’m making a new break timer app for GNOME. First, thank you, dear readers, for your feedback and support so far! It really helps to know other people are interested in this.

The last two weeks have been about tying up loose ends so I don’t get bogged down later on. First, I removed all traces of the old working title. This application is called GNOME Break Timer, now, instead of having several different names (and things that looked like names) strewn about. It probably only bothered me, but I’m really glad to have some logic on that front.

I got our cool introductory slideshow running. It appears if you launch Break Timer and breaks are not enabled. So, it will appear when you start Break Timer for the first time, and if you happen to turn it off at some point and want to start using it again. GtkStack was fantastic for this. It’s really nice to see GTK making animated transitions so easy, and apparently doing a pretty good job drawing them. I think it will be really exciting when applications are doing more of this in the future.

Incidentally, I updated the settings application to optionally support GTK 3.9+ with its very cool new gtk_window_set_titlebar function! I was a little disappointed to learn that I have to add the close button to the HeaderBar myself at the moment, which seems a little silly. So, I did some guessing about best practice (and borrowed some code from GNOME Clocks), then I made a little custom widget for the problem so I wouldn’t have to think about it any more.

#if HAS_GTK_3_10
using Gtk;
#else
using Gd;
#endif

/**
 * A Gtk.HeaderBar that expects to be set as the titlebar for a Gtk.Window.
 * If it is in titlebar mode, it adds a conventional close button and adjusts
 * its own titles accordingly.
 */
public class WindowHeaderBar : HeaderBar { // Gtk.HeaderBar or Gd.HeaderBar
	private weak Gtk.Window owner_window;
	private Gtk.Button close_button;
	private Gtk.Separator close_separator;

	private bool is_titlebar;

	public WindowHeaderBar(Gtk.Window window) {
		this.owner_window = window;

		this.close_separator = new Gtk.Separator (Gtk.Orientation.VERTICAL);
		this.close_separator.valign = Gtk.Align.FILL;

		this.close_button = new Gtk.Button();
		this.close_button.set_image(
			new Gtk.Image.from_icon_name("window-close-symbolic", Gtk.IconSize.MENU)
		);
		this.close_button.get_style_context().add_class("image-button");
		this.close_button.relief = Gtk.ReliefStyle.NONE;
		this.close_button.valign = Gtk.Align.CENTER;
		this.close_button.clicked.connect(this.on_close_button_clicked_cb);

		this.realize.connect(() => {
			this.pack_end(this.close_separator);
			this.pack_end(this.close_button);
		});
	}

	public new void set_title(string? title) {
		if (this.is_titlebar && title == null) {
			title = this.owner_window.title;
		}
		base.set_title(title);
	}

	public void set_is_titlebar(bool is_titlebar) {
		this.is_titlebar = is_titlebar;
		this.close_separator.set_visible(is_titlebar);
		this.close_button.set_visible(is_titlebar);
		this.set_title(this.title);
	}

	private void on_close_button_clicked_cb() {
		var event = new Gdk.Event (Gdk.EventType.DESTROY);
		event.any.window = this.owner_window.get_window();
		event.any.send_event = 1;
		Gtk.main_do_event (event);
	}
}

This widget belongs to a particular GtkWindow. When it is being used as a titlebar, it shows a Close button and borrows the title from that window when one is not set for the HeaderBar itself. You can see that happening in my video demo of the welcome slideshow. If it is not used as a titlebar, the widget behaves as usual – so, it looks like one of these:

Screenshot from 2013-07-26 19:20:37

Screenshot from 2013-07-26 19:20:19

Unfortunately, I can’t find a nice way for the widget to detect when it’s being used as a window’s titlebar, so it needs a set_is_titlebar method that gets called by the owner. Other than that, the ugliness is self-contained.

Another small change I’m very happy with is to how the break notifications appear. They are persistent, now, so as long as you need to take a break there will be a notification for it in the message tray. This makes them much tidier, and harder to miss. Now I just wish there was a way to have a notification banner stay open without needing to mark it as “critical” priority. I hate the idea that a “take a break” notification could take priority over a “low battery” notification…

How to install GNOME Break Timer

As always, I have been messing with my packages. If you want to try the latest test of GNOME Break Timer, there are two things you can do:

  • You can download this archive for the latest release and do the usual ./configure, make and make install thing. To build on Debian, it depends on libx11-dev, libxtst-dev, libxi-dev, as well as valac and libgtk3-dev (>= 3.7) and the other usual suspects.
  • Or, if you’re running Ubuntu 13.10 (or 13.04 with GNOME 3.8 installed), there’s a working PPA, so open a terminal and enter sudo add-apt-repository ppa:brainbreak/experimental && sudo apt-get update && sudo apt-get install gnome-break-timer. Note that the package has a different name than before (even though the repository is the same), so if you installed the brainbreak-experimental package earlier (thank you very much, by the way!), you’ll need to install gnome-break-timer anyway.

Next week, I’m going to make a serious effort to gather feedback on how this is working. I’m thinking of hooking up Piwik for some rudimentary statistics-gathering within the app. I’m not sure how much trouble it would be, or if it would be worth doing. We’ll see, anyway. I will also be looking at things outside Break Timer that could be changed to enable certain features, such as better lock screen notifications out of the box. GUADEC would be a perfect venue for that sort of thing, but unfortunately I won’t be there. (Next year, maybe?). Still, even if it’s just on IRC and mailing lists, it will be nice to poke my head outside this little corner I’ve been working in.