danilobellini / dose

Traffic light/signal/semaphore GUI showing the result of a test command job triggered by a file modification
GNU General Public License v3.0
44 stars 8 forks source link

Add a timer component #3

Open samuelgrigolato opened 10 years ago

samuelgrigolato commented 10 years ago

As suggested by previous dojos participants, it would be nice to have a Pomodoro like component built in dose.

I'm creating this issue to improve the requirements of the feature, before any coding. Following is my understanding as a starting point:

danilobellini commented 10 years ago

I think such a timer should:

  1. Be near to the semaphore, in the same window (below? configurable?);
  2. Be possible to show/hide it (e.g. a new item for the popup menu);
  3. Have a digital "minutes:seconds" display with a monospaced font;
  4. Have a time-varying colored numbers/background (a colormap to let people know when time is almost over, without any need to "read" its written numbers);
  5. Warn the user when time is over (message box? audio? both?);
  6. Change accordingly the window shape (probably it won't be just a rounded rectangle anymore).

The timer duration can also be changed by [double] clicking over the numbers, what do you think?

samuelgrigolato commented 10 years ago

My cents:

1: configurable, below by default. 2: showing by default. 3: +1 monospaced, will ease the math and developers tend to prefer monospaced fonts anyway =]. 4: nice feature! 5: Message box seems to be an annoying thing, I would prefer a change to the frame background color and an audio cue.

6: What did you mean with 'change accordingly window shape'? I would suggest that the new minimum frame size in pixels need to be the minimum value capable of presenting the time horizontally (suppressing the buttons). Implementing more complex shapes like an "L" or "T" seems not to be a necessary feature, people will most likely use the smallest rectangular version (IMHO).

About the mechanism to change the duration by double clicking the numbers: the value will change automatically (based on a set of pre-defined values) or an input popup will be displayed, allowing the user to type any value?

danilobellini commented 10 years ago

1: Configurations are "above" and "below". Making it available to the left or to the right would need a multirow representation, which can be done, but not in a first version.

2.1: I think it should be easy to show/hide it, even from command line (e.g. dose.py --timer 4:33 py.test would call py.test with the timer already set on 4 minutes and 33 seconds).

2.2: I agree there's a problem with the "hidden by default": people may not even know that a timer exists. But a "shown by default" should have a fast or a memoizable way to hide the timer. Perhaps it would be better to keep something like a ~/.doserc file to keep last used configuration (skip pattern, timer, size, position, etc.).

3: We can make an open font for that. =)

5.1: Instead of a message box, dose.py may "shake" itself, flicker, change its color/size in a "heartbeating"-like way, etc.. Even a message is ok, it just annoys when it changes the window that has the focus, and I think that's not needed (nor desired) at all.

5.2: Sound would add a new requirement for dose.py (e.g. PyAudio, PyGame, ...), besides the wave itself. To keep dose.py a "one-filer" project, the sound should be done by a synthesis algorithm. Also, a "tic-tac" with fade in for the last 30 seconds would be nice.

6.1: dose.py uses the rounded_rectangle_region() function to change the wx.Frame widget shape (i.e., the window shape itself), allowing rounded borders. If we add something below dose, its shape should be updated accordingly, perhaps with the small rounded borders making a small "cut" in the middle of the window.

6.2: Shapes like "L" or "T" might look nice, but I don't know if these shapes would give a better GUI experience for moving and resizing/reshaping, and these probably won't be done in a first implementation of a timer feature. But I don't think we need to keep only features that are "necessary", e.g., anyone can add an incrementing sequence memory game in dose.py as an easter egg.

Double clicking the number can be the same as a right click -> "Set timer interval" (or something like) in a input box popup. But this can also insert/show an edit box in place. or can show arrows up/down to allow changing the value by clicking. Or perhaps all of these.

samuelgrigolato commented 10 years ago

I'm thinking of implementing the following items as a first contribution:

New popup options:

When I finish these we can go back and think about other cool things to add, like the open monospaced font, the heartbeat behavior and the inline editor controls.

danilobellini commented 10 years ago

Config file support might have "levels" of fallback (like git config). The config file would be:

  1. Local (a config for that specific project), os.curdir
  2. User, os.path.expanduser("~")
  3. Global, like "/etc"
  4. Default (e.g. hardcoded)

At first, two levels seem to be needed: home and default configuration. I think a global config isn't needed at all, unless it is the way the defaults are stored. Local config might be added afterwards. The other way around (storing config in the current dir instead of starting with an user config) would be as annoying as the Windows "Thumbs.db" files, and that's not something needed for coding dojos. So, after all, I don't even know if something else in a config file support is helpful.

The config file name might be ".dose.conf", ".doseconf", ".doserc", or something else. For example, Spyder uses "~/.spyder2/.spyder.ini" as its config file. I see no need for a subdirectory, and I liked ".doserc", but ending with ".ini" or ".conf" would help Windows users when finding an app to edit it (based on file extension).

File format would be a JSON, an INI-like with ConfigParser, a XML, an AST-parsed Python file (to ensure only assignments are done, or perhaps another Python syntax subset), etc..

I'm waiting for the pull request. =)

samuelgrigolato commented 10 years ago

Is there any way to make a wx.StaticText component "stretch" the text until it fills the parent panel? I did some research but had no luck (it works only the other way around, i.e., the component size matches the text width/height automatically). I'm almost biting the bullet and writing my own digit/colon drawer on top of wx.GraphicsContext.

danilobellini commented 10 years ago

Yes, there is. You can bind the resize event to change the font size. To find the font size, this script might help:

import wx

max_width = 10 # pixels
max_height = 20 # pixels

app = wx.App()
font = wx.FontFromPixelSize((max_width, max_height),
         family = wx.FONTFAMILY_DEFAULT,
         style = wx.FONTSTYLE_NORMAL,
         weight = wx.FONTWEIGHT_NORMAL,
       )
dc = wx.MemoryDC()
dc.SetFont(font)

print dc.GetTextExtent("Test") # => (29, 16)
samuelgrigolato commented 10 years ago

This script did the job well, thanks! =]