1/*
2 * Copyright 2009, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "SettingsWindow.h"
8
9#include <stdio.h>
10#include <stdlib.h>
11
12#include <Catalog.h>
13#include <LayoutBuilder.h>
14#include <GroupLayoutBuilder.h>
15#include <Slider.h>
16#include <String.h>
17
18#undef B_TRANSLATION_CONTEXT
19#define B_TRANSLATION_CONTEXT "SettingsWindow"
20
21
22static const uint32 kMsgUpdateTimeInterval = 'upti';
23
24static const bigtime_t kUpdateIntervals[] = {
25	25, 50, 75, 100, 250, 500, 1000, 2000
26};
27static const size_t kNumUpdateIntervals
28	= sizeof(kUpdateIntervals) / sizeof(kUpdateIntervals[0]);
29
30
31class IntervalSlider : public BSlider {
32public:
33	IntervalSlider(const char* label, BMessage* message, uint32 levels)
34		: BSlider("intervalSlider", label, message, 0, levels - 1, B_HORIZONTAL)
35	{
36		BString min(_TextFor(0));
37		BString max(_TextFor(levels - 1));
38		SetLimitLabels(min.String(), max.String());
39		SetHashMarks(B_HASH_MARKS_BOTTOM);
40		SetHashMarkCount(levels);
41		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
42
43		if (message != NULL)
44			SetModificationMessage(new BMessage(*message));
45	}
46
47	void SetInterval(bigtime_t interval)
48	{
49		interval /= 1000;
50
51		// Find closest index
52		int32 bestDiff = INT32_MAX;
53		uint32 bestIndex = 0;
54		for (uint32 i = 0; i < kNumUpdateIntervals; i++) {
55			int32 diff = abs(kUpdateIntervals[i] - interval);
56			if (diff < bestDiff) {
57				bestDiff = diff;
58				bestIndex = i;
59			}
60		}
61
62		SetValue(bestIndex);
63	}
64
65	virtual const char* UpdateText() const
66	{
67		return _TextFor(Value());
68	}
69
70private:
71	const char* _TextFor(uint32 level) const
72	{
73		if (level >= kNumUpdateIntervals)
74			return NULL;
75
76		bigtime_t interval = kUpdateIntervals[level];
77		if ((interval % 1000) == 0) {
78			snprintf(fText, sizeof(fText), B_TRANSLATE("%lld sec."),
79				(long long int)interval / 1000);
80		} else
81			snprintf(fText, sizeof(fText), B_TRANSLATE("%lld ms"), (long long int)interval);
82
83		return fText;
84	}
85
86	mutable char	fText[64];
87};
88
89
90//	#pragma mark -
91
92
93SettingsWindow::SettingsWindow(ActivityWindow* target)
94	: BWindow(_RelativeTo(target),
95		B_TRANSLATE_CONTEXT("Settings", "ActivityWindow"), B_FLOATING_WINDOW,
96	   	B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
97	fTarget(target)
98{
99	fIntervalSlider = new IntervalSlider(B_TRANSLATE("Update time interval:"),
100		new BMessage(kMsgUpdateTimeInterval), kNumUpdateIntervals);
101	fIntervalSlider->SetInterval(target->RefreshInterval());
102
103	// controls pane
104	BLayoutBuilder::Group<>(this, B_VERTICAL)
105		.Add(fIntervalSlider)
106		.SetInsets(B_USE_WINDOW_SPACING);
107
108	if (target->IsAlwaysOnTop())
109		SetFeel(B_MODAL_ALL_WINDOW_FEEL);
110
111	MoveOnScreen(B_MOVE_IF_PARTIALLY_OFFSCREEN);
112}
113
114
115SettingsWindow::~SettingsWindow()
116{
117}
118
119
120void
121SettingsWindow::MessageReceived(BMessage* message)
122{
123	switch (message->what) {
124		case kMsgUpdateTimeInterval:
125		{
126			int32 level = 0;
127			if (message->FindInt32("be:value", &level) != B_OK)
128				break;
129
130			BMessage update(kMsgTimeIntervalUpdated);
131			update.AddInt64("interval", kUpdateIntervals[level] * 1000LL);
132
133			fTarget.SendMessage(&update);
134			break;
135		}
136
137		default:
138			BWindow::MessageReceived(message);
139			break;
140	}
141}
142
143
144bool
145SettingsWindow::QuitRequested()
146{
147	return true;
148}
149
150
151BRect
152SettingsWindow::_RelativeTo(BWindow* window)
153{
154	BRect frame = window->Frame();
155	return BRect(frame.right - 150, frame.top + frame.Height() / 4,
156		frame.right + 200, frame.top + frame.Height() / 4 + 50);
157}
158