31 #define AWAR_DIM_ACTIVE(dim) dimension_awar(dim, "active")
32 #define AWAR_FIELD(dim) dimension_awar(dim, "field")
33 #define AWAR_ACI(dim) dimension_awar(dim, "aci")
34 #define AWAR_VALUE_MIN(dim) dimension_awar(dim, "min")
35 #define AWAR_VALUE_MAX(dim) dimension_awar(dim, "max")
43 float min_value, max_value;
46 static bool safe_atof(
const char *strval,
float& res) {
51 res = strtof(strval, &end);
58 float span = max_value-min_value;
59 factor = span != 0.0 ? 1.0/span : 1/0.00001;
64 FieldReader(
const char *fieldname_,
const char *aci_,
float minVal,
float maxVal) :
65 fieldname(fieldname_),
67 is_hkey(strchr(fieldname,
'/')),
88 if (fieldname && gb_item) {
107 bool converted = safe_atof(applied, val);
109 if (!converted)
return NAN;
117 bool converted = safe_atof(content, val);
119 if (!converted)
return NAN;
125 const float rval = (val-min_value)*factor;
147 reader[dim++] = added;
159 reader[1].calc_value(gb_item));
161 reader[1].calc_value(gb_item),
162 reader[2].calc_value(gb_item));
178 mutable string item_dbpath;
181 const char *get_fieldname(
int dim)
const {
193 static bool is_ACI(
const char *aci) {
197 const char *get_ACI(
int dim)
const {
202 if (is_ACI(aci))
return aci;
210 const char *fieldname = get_fieldname(dim);
214 return FieldReader(fieldname, get_ACI(dim), minVal, maxVal);
222 for (
int dim = 0; dim<get_max_dimension(); ++dim) {
229 if (reader.
isNull()) reader = make_multi_field_reader();
233 bool knows_item_dbpath()
const {
234 if (item_dbpath.empty()) {
238 if (ipath) item_dbpath =
string(ipath);
241 return !item_dbpath.empty();
244 void update_db_callbacks(
const FieldSet& wanted) {
245 if (knows_item_dbpath()) {
246 DatabaseCallback dbcb = makeDatabaseCallback(ItemFieldShader::field_updated_in_DB_cb,
this);
254 for (FieldSet::const_iterator installed = hcbs_installed.begin(); installed != hcbs_installed.end(); ++installed) {
255 if (wanted.find(*installed) == wanted.end()) {
256 string field_db_path = item_dbpath +
'/' + *installed;
261 for (FieldSet::const_iterator missing = wanted.begin(); missing != wanted.end(); ++missing) {
262 if (hcbs_installed.find(*missing) == hcbs_installed.end()) {
263 string field_db_path = item_dbpath +
'/' + *missing;
267 hcbs_installed = wanted;
271 void add_used_fields(
FieldSet& wanted)
const {
272 const char *fname0 = get_fieldname(0);
273 if (fname0) wanted.insert(fname0);
275 void setup_db_callbacks(
bool install) {
277 if (install) add_used_fields(wanted);
278 update_db_callbacks(wanted);
294 return get_field_reader().calc_value(gb_item);
299 return get_field_reader().get_dimension();
309 char *store_config() const OVERRIDE;
310 void load_or_reset_config(const
char *cfgstr) OVERRIDE;
312 void activate(
bool on) OVERRIDE {
314 setup_db_callbacks(on);
319 setup_db_callbacks(
true);
328 void scan_value_range_cb(
int dim);
334 for (
int dim = 0; dim<get_max_dimension(); ++dim) {
346 for (
int dim = 0; dim<get_max_dimension(); ++dim) {
357 init_config_definition(cdef);
363 init_config_definition(cdef);
365 if (cfgstr) cdef.
write(cfgstr);
371 AW_window_simple *aws =
new AW_window_simple;
374 aws->init(awr, wid.c_str(), get_description().c_str());
377 aws->auto_space(5, 5);
378 aws->button_length(8);
380 int y0 = aws->get_at_yposition();
383 aws->create_button(
"CLOSE",
"CLOSE",
"O");
386 aws->create_button(
"HELP",
"HELP");
390 int y = aws->get_at_yposition();
391 const char *header[] = {
"Use",
"Field",
"ACI",
"min",
"max", };
395 x[0] = aws->get_at_xposition();
399 for (
int dim = 0; dim<get_max_dimension(); ++dim) {
403 if (!dim) x[h++] = aws->get_at_xposition();
407 if (!dim) x[h++] = aws->get_at_xposition();
408 aws->create_input_field(
AWAR_ACI(dim), 30);
410 const int VALCOL = 9;
411 if (!dim) x[h++] = aws->get_at_xposition();
413 if (!dim) x[h++] = aws->get_at_xposition();
416 aws->callback(makeWindowCallback(scan_value_range_cb,
this, dim));
422 for (
int h = 0; h<HCOUNT; ++h) {
424 aws->create_button(
NULp, header[h]);
429 aw_config->activate();
436 char *e = strchr(s, 0)-1;
459 min(numeric_limits<
T>::max()),
460 max(numeric_limits<
T>::min())
467 void track(
const char *
str);
485 bool have_aci = is_ACI(aci);
489 error =
"Select field to scan";
495 bool seen_field =
false;
496 bool is_hierarchical = strchr(fieldname,
'/');
507 GBDATA *gb_field = is_hierarchical
524 ilimit.
track(applied);
525 flimit.
track(applied);
532 switch (field_type) {
558 bool seen_float = flimit.
seen();
559 bool seen_int = ilimit.
seen();
561 if (seen_float || seen_int) {
562 bool use_float = seen_float && (!seen_int || ilimit.
get_max()<flimit.
get_max());
571 if (shading_useless) {
572 error =
GBS_global_string(
"Using field '%s' for shading is quite useless", fieldname);
576 error =
"Failed to scan range (no value encountered)";
597 #define TEST_READER_READS(reader,species,expected) TEST_EXPECT_EQUAL(ValueTuple::make((reader).calc_value(species))->inspect(), expected)
598 #define TEST_READER_UNDEF(reader,species) TEST_READER_READS(reader, species, "<undef>")
599 #define TEST_MULTI_READS(reader,species,expected) TEST_EXPECT_EQUAL((reader).calc_value(species)->inspect(), expected)
600 #define TEST_MULTI_UNDEF(reader,species) TEST_MULTI_READS(reader,species, "<undef>")
602 void TEST_FieldReader() {
607 GBDATA *gb_species, *gb_species2, *gb_species_outofbounds, *gb_species_no_field;
609 const char *FIELD_FLOAT =
"float";
610 const char *FIELD_INT =
"int";
611 const char *FIELD_STRING =
"string";
640 FieldReader aciReader(FIELD_STRING,
"|contains(unit)", 0, 1);
651 TEST_READER_UNDEF(nullReader,
NULp);
652 TEST_READER_UNDEF(missingReader,
NULp);
653 TEST_READER_UNDEF(floatReader,
NULp);
654 TEST_READER_UNDEF(intReader,
NULp);
655 TEST_READER_UNDEF(stringReader,
NULp);
656 TEST_READER_UNDEF(aciReader,
NULp);
658 TEST_READER_UNDEF(nullReader, gb_species);
659 TEST_READER_UNDEF(missingReader, gb_species);
661 TEST_READER_READS(floatReader, gb_species,
"(0.750)");
662 TEST_READER_READS(intReader, gb_species,
"(0.500)");
663 TEST_READER_READS(stringReader, gb_species,
"(0.667)");
664 TEST_READER_READS(aciReader, gb_species,
"(5.000)");
666 TEST_READER_READS(floatReader, gb_species2,
"(0.100)");
667 TEST_READER_READS(intReader, gb_species2,
"(0.990)");
668 TEST_READER_READS(stringReader, gb_species2,
"(0.506)");
669 TEST_READER_READS(aciReader, gb_species2,
"(0.000)");
672 TEST_READER_READS(floatReader, gb_species_outofbounds,
"(-0.500)");
673 TEST_READER_READS(intReader, gb_species_outofbounds,
"(99.990)");
674 TEST_READER_READS(stringReader, gb_species_outofbounds,
"(-82.971)");
675 TEST_READER_READS(aciReader, gb_species_outofbounds,
"(0.000)");
677 TEST_READER_UNDEF(floatReader, gb_species_no_field);
678 TEST_READER_UNDEF(intReader, gb_species_no_field);
679 TEST_READER_UNDEF(stringReader, gb_species_no_field);
680 TEST_READER_UNDEF(aciReader, gb_species_no_field);
691 TEST_MULTI_READS(multi, gb_species,
"(0.750)");
692 TEST_MULTI_READS(multi, gb_species2,
"(0.100)");
693 TEST_MULTI_READS(multi, gb_species_outofbounds,
"(-0.500)");
694 TEST_MULTI_UNDEF(multi, gb_species_no_field);
GBDATA * GB_open(const char *path, const char *opent)
bool is_single_value() const
void load_or_reset_config(const char *cfgstr) OVERRIDE
ShaderPluginPtr makeItemFieldShader(BoundItemSel &itemtype)
void add(const char *awar_name, const char *config_name)
long GB_read_int(GBDATA *gbd)
GB_ERROR GB_add_hierarchy_callback(GBDATA *gb_main, const char *db_path, GB_CB_TYPE type, const DatabaseCallback &dbcb)
return string(buffer, length)
void scan_value_range_cb(int dim)
GBDATA * GB_searchOrCreate_string(GBDATA *gb_container, const char *fieldpath, const char *default_value)
static ShadedValue make(float f)
GBDATA * get_any_item() const
const char * make_limit_string(bool use_float, float f, int i)
ValueTuple::ShadedValue ShadedValue
char * GB_read_as_string(GBDATA *gbd)
#define AWAR_VALUE_MIN(dim)
float calc_value(GBDATA *gb_item) const
const char * GBS_global_string(const char *templat,...)
void AW_POPDOWN(AW_window *window)
bool isNull() const
test if SmartPtr is NULp
FieldReader(const char *fieldname_, const char *aci_, float minVal, float maxVal)
#define ARRAY_ELEMS(array)
void setNull()
set SmartPtr to NULp
#define NO_FIELD_SELECTED
GB_ERROR GB_incur_error_if(bool error_may_occur)
AW_awar * add_callback(const RootCallback &cb)
struct Unfixed_cb_parameter * UNFIXED
void create_itemfield_selection_button(AW_window *aws, const FieldSelDef &selDef, const char *at)
void init_specific_awars(AW_root *awr) OVERRIDE
const char * read_char_pntr() const
GB_ERROR GB_await_error()
static AW_root * SINGLETON
WindowCallback makeHelpCallback(const char *helpfile)
#define TEST_EXPECT(cond)
ShadedValue shade(GBDATA *gb_item) const OVERRIDE
GB_TYPES GB_read_type(GBDATA *gbd)
#define AWAR_VALUE_MAX(dim)
char * store_config() const OVERRIDE
static void scan_value_range_cb(AW_window *, ItemFieldShader *shader, int dim)
#define TEST_REJECT(cond)
#define TEST_REJECT_NULL(n)
static void error(const char *msg)
int get_dimension() const
GBDATA * GB_searchOrCreate_int(GBDATA *gb_container, const char *fieldpath, long default_value)
float GB_read_float(GBDATA *gbd)
int get_dimension() const OVERRIDE
static void setup_changed_cb(AW_root *, ItemFieldShader *shader)
AW_awar * awar(const char *awar)
#define AWAR_DIM_ACTIVE(dim)
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
GB_ERROR GB_remove_hierarchy_callback(GBDATA *gb_main, const char *db_path, GB_CB_TYPE type, const DatabaseCallback &dbcb)
void add_reader(const FieldReader &added)
bool customizable() const OVERRIDE
GBDATA * GB_searchOrCreate_float(GBDATA *gb_container, const char *fieldpath, float default_value)
void customize(AW_root *awr) OVERRIDE
static ShadedValue undefined()
ItemFieldShader(const BoundItemSel &itemtype_)
const char * GBS_static_string(const char *str)
void trigger_reshade_if_active_cb(ReshadeMode mode)
const char * GB_get_db_path(GBDATA *gbd)
void aw_message(const char *msg)
GBDATA * GBT_find_or_create_species(GBDATA *gb_main, const char *name, bool markCreated)
void track(const char *str)
GB_ERROR write_string(const char *aw_string)
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
GB_transaction ta(gb_var)
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
ShadedValue calc_value(GBDATA *gb_item) const
int get_max_dimension() const
#define TEST_EXPECT_EQUAL(expr, want)
GBDATA * GB_entry(GBDATA *father, const char *key)
void aw_message_if(GB_ERROR error)
CONSTEXPR long FIELD_FILTER_STRING_READABLE
char * GBS_global_string_copy(const char *templat,...)
void GB_close(GBDATA *gbd)
void track(const char *str)
void write(const char *cfgStr) const
GB_write_int const char s