3
* Copyright (C) 2004-2008 Jean-Yves Lefort <jylefort@brutele.be>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 3 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
#include "lm-non-linear-range.h"
26
const LMNonLinearRangeBlock *blocks;
30
static GQuark info_quark = 0;
36
info_quark = g_quark_from_static_string("lm-non-linear-range-info");
40
get_info (GtkRange *range)
44
g_return_val_if_fail(GTK_IS_RANGE(range), NULL);
45
g_return_val_if_fail(info_quark != 0, NULL);
47
info = g_object_get_qdata(G_OBJECT(range), info_quark);
48
g_return_val_if_fail(info != NULL, NULL);
54
get_block_len (const LMNonLinearRangeBlock *block)
56
g_return_val_if_fail(block != NULL, -1);
58
return ((block->max - block->min) / block->step) + 1;
62
lm_non_linear_range_setup_static (GtkRange *range,
63
const LMNonLinearRangeBlock *blocks,
70
g_return_if_fail(GTK_IS_RANGE(range));
71
g_return_if_fail(blocks != NULL);
72
g_return_if_fail(num_blocks > 0);
76
info = g_new0(RangeInfo, 1);
77
info->blocks = blocks;
78
info->num_blocks = num_blocks;
80
g_object_set_qdata_full(G_OBJECT(range), info_quark, info, g_free);
82
for (i = 0; i < num_blocks; i++)
83
num_values += get_block_len(&blocks[i]);
85
gtk_range_set_range(range, 0, num_values - 1);
89
lm_non_linear_range_get_value (GtkRange *range)
96
g_return_val_if_fail(GTK_IS_RANGE(range), -1);
98
info = get_info(range);
100
raw = (int) gtk_range_get_value(range);
102
for (i = 0; i < info->num_blocks; i++)
104
const LMNonLinearRangeBlock *block = &info->blocks[i];
107
next_offset = offset + get_block_len(block);
109
if (raw >= offset && raw < next_offset)
110
return block->min + (raw - offset) * block->step;
112
offset = next_offset;
115
g_assert_not_reached();
120
value_to_index (RangeInfo *info, int value)
125
/* if smaller than the first value, use the first value */
126
if (value < info->blocks[0].min)
129
for (i = 0; i < info->num_blocks; i++)
131
const LMNonLinearRangeBlock *block = &info->blocks[i];
133
if (value >= block->min && value <= block->max)
139
/* round the value to the nearest step */
140
rounded = lround((double) value / block->step) * block->step;
142
for (j = block->min, index = 0; j <= block->max; j += block->step, index++)
144
return offset + index;
146
g_assert_not_reached();
149
offset += get_block_len(block);
152
/* block not found: fallback to the maximum value */
157
* If the value is not found in the blocks, the nearest existing value
161
lm_non_linear_range_set_value (GtkRange *range, int value)
163
g_return_if_fail(GTK_IS_RANGE(range));
165
gtk_range_set_value(range, value_to_index(get_info(range), value));