#ifndef DATASOURCE_H
#define DATASOURCE_H
-.string stringfield_null;
CLASS(DataSource, Object)
- ATTRIB(DataSource, entryName, .string, stringfield_null)
- ATTRIB(DataSource, entryIcon, .string, stringfield_null)
- ATTRIB(DataSource, entryIconPrefix, string, "")
- METHOD(DataSource, getEntry, entity(int))
- METHOD(DataSource, indexOf, int(string))
- METHOD(DataSource, reload, int(string))
+ /**
+ * get entry `i` passing `name` and `icon` through `returns` if it is not null
+ * returns `DataSource_false` if out of bounds
+ * otherwise returns an entity or `DataSource_true`
+ */
+ METHOD(DataSource, getEntry, entity(int i, void(string name, string icon) returns))
+ /** return the index of the first match for `find`. optional */
+ METHOD(DataSource, indexOf, int(string find))
+ /** reload all entries matching `filter` returning how many matches were found */
+ METHOD(DataSource, reload, int(string filter))
+ /** cleanup on shutdown. optional */
METHOD(DataSource, destroy, void(entity))
+ entity DataSource_true;
+ entity DataSource_false;
+ INIT_STATIC(DataSource) {
+ DataSource_true = new(dummy);
+ DataSource_false = NULL;
+ }
ENDCLASS(DataSource)
#endif
if (cvar("developer")) X(NEW(DebugSource), _("Debug"), "gametype_ons") \
/**/
CLASS(TopicSource, DataSource)
- .string icon, name;
- ATTRIB(TopicSource, entryIcon, .string, icon)
- ATTRIB(TopicSource, entryName, .string, name)
- METHOD(TopicSource, getEntry, entity(int))
- entity TopicSource_getEntry(int i) {
- static entity e;
- if (!e) e = new(entry);
+ METHOD(TopicSource, getEntry, entity(int, void(string, string)))
+ entity TopicSource_getEntry(int i, void(string, string) returns) {
int idx = 0;
- .string en = name, ei = icon;
- #define TOPIC(src, name, icon) if (idx++ == i) { e.(en) = name; e.(ei) = icon; return e; }
- TOPICS(TOPIC)
+ #define TOPIC(src, name, icon) if (idx++ == i) { if (returns) returns(name, icon); return DataSource_true; }
+ TOPICS(TOPIC);
#undef TOPIC
- e.en = "undefined"; e.ei = "undefined";
- return e;
+ if (returns) returns("undefined", "undefined");
+ return DataSource_false;
}
METHOD(TopicSource, reload, int(string))
int TopicSource_reload(string filter) {
- int i = 0;
- #define TOPIC(src, name, icon) i++;
- TOPICS(TOPIC)
+ int n = 0;
+ #define TOPIC(src, name, icon) n++;
+ TOPICS(TOPIC);
#undef TOPIC
- return i;
+ return n;
}
ENDCLASS(TopicSource)
CLASS(DebugSource, DataSource)
- .string name, icon;
- ATTRIB(DebugSource, entryName, .string, name)
- ATTRIB(DebugSource, entryIcon, .string, icon)
+ .entity nextdebug;
+ entity find_debug() {
+ entity head = NULL, tail = NULL;
+ for (entity it = NULL; (it = nextent(it)); ) {
+ if (!it.instanceOfObject) continue;
+ if (it.instanceOfItem) continue;
+ if (it.classname == "vtbl") continue;
+ if (!tail) {
+ tail = head = it;
+ } else {
+ tail.nextdebug = it;
+ tail = it;
+ }
+ }
+ return head;
+ }
string DebugSource_activeFilter = "";
- .entity chain;
- METHOD(DebugSource, getEntry, entity(int))
- entity DebugSource_getEntry(int i) {
+ METHOD(DebugSource, getEntry, entity(int, void(string, string)))
+ entity DebugSource_getEntry(int i, void(string, string) returns) {
int idx = 0;
entity e;
- for (e = findchainfloat(instanceOfObject, true); e; e = e.chain) {
- if (e.classname == "vtbl") continue;
- if (e.instanceOfItem) continue;
+ for (e = find_debug(); e; e = e.nextdebug) {
if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue;
if (idx++ == i) break;
}
- static entity entry;
- if (!entry) entry = new(entry);
- entry.name = sprintf("entity %i", e);
- entry.icon = "";
- return entry;
+ if (returns) returns(sprintf("entity %i", e), "");
+ return e;
}
METHOD(DebugSource, reload, int(string))
int DebugSource_reload(string filter) {
DebugSource_activeFilter = filter;
int idx = 0;
entity e;
- for (e = findchainfloat(instanceOfObject, true); e; e = e.chain) {
- if (e.classname == "vtbl") continue;
- if (e.instanceOfItem) continue;
+ for (e = find_debug(); e; e = e.nextdebug) {
if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue;
idx++;
}
#include "../../common/mapinfo.qh"
CLASS(GametypeSource, DataSource)
.string mdl, message;
- ATTRIB(GametypeSource, entryName, .string, message)
- ATTRIB(GametypeSource, entryIcon, .string, mdl)
- ATTRIB(GametypeSource, entryIconPrefix, string, "gametype_")
- METHOD(GametypeSource, getEntry, entity(int))
- entity GametypeSource_getEntry(int i) { return MAPINFO_TYPES[i]; }
+ METHOD(GametypeSource, getEntry, entity(int, void(string, string)))
+ entity GametypeSource_getEntry(int i, void(string, string) returns) {
+ entity e = MAPINFO_TYPES[i];
+ if (returns) returns(e.message, strcat("gametype_", e.mdl));
+ return e;
+ }
METHOD(GametypeSource, reload, int(string))
int GametypeSource_reload(string filter) { return MAPINFO_TYPE_COUNT; }
ENDCLASS(GametypeSource)
CLASS(MapSource, DataSource)
- .string icon, name;
- ATTRIB(MapSource, entryIcon, .string, icon)
- ATTRIB(MapSource, entryName, .string, name)
- METHOD(MapSource, getEntry, entity(int))
+ METHOD(MapSource, getEntry, entity(int, void(string, string)))
+ entity MapSource_getEntry(int i, void(string, string) returns)
+ {
+ if (!MapInfo_Get_ByID(i)) return DataSource_false;
+ string path = strcat("/maps/", MapInfo_Map_bspname);
+ string img = draw_PictureSize(path) ? path : "nopreview_map";
+ if (returns) returns(MapInfo_Map_titlestring, img);
+ MapInfo_ClearTemps();
+ return DataSource_true;
+ }
METHOD(MapSource, indexOf, int(string))
+ int MapSource_indexOf(string s)
+ {
+ MapInfo_FindName(s);
+ return MapInfo_FindName_firstResult;
+ }
METHOD(MapSource, reload, int(string))
+ int MapSource_reload(string s)
+ {
+ MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 0);
+ if (s) MapInfo_FilterString(s);
+ return MapInfo_count;
+ }
+ METHOD(MapSource, destroy, void(entity))
+ void MapSource_destroy(entity this) { MapInfo_Shutdown(); }
ENDCLASS(MapSource)
#include "dialog_media_guide_topics.qc"
#undef TOPIC
entries.source = found;
entries.refilter(entries);
+ entries.setSelected(entries, 0);
}
void XonoticGuideTab_entryChangeNotify(entity, entity this)
{
entity desc = this.descriptionPane;
- desc.setDescription(desc, sprintf("item %.0f\n", this.entryList.selectedItem));
-}
-
-entity MapSource_getEntry(int i)
-{
- if (!MapInfo_Get_ByID(i)) return NULL;
- static entity e;
- if (!e) e = new(entry);
- e.name = MapInfo_Map_titlestring;
- string path = strcat("/maps/", MapInfo_Map_bspname);
- string img = draw_PictureSize(path) ? path : "nopreview_map";
- e.icon = img;
- MapInfo_ClearTemps();
- return e;
-}
-
-int MapSource_indexOf(string s)
-{
- MapInfo_FindName(s);
- return MapInfo_FindName_firstResult;
-}
-
-int MapSource_reload(string s)
-{
- MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 0);
- if (s) MapInfo_FilterString(s);
- return MapInfo_count;
+ entity entries = this.entryList;
+ entity e = entries.source.getEntry(entries.selectedItem, func_null);
+ string s = e.description;
+ string s2 = s ? s : _("No description");
+ if (cvar("developer")) { if (!s) s2 = sprintf("entity %i\n%s", e, s2); }
+ desc.setDescription(desc, s2);
}
-void MapSource_destroy(entity this) { MapInfo_Shutdown(); }
-
#endif
#ifdef IMPLEMENTATION
+string XonoticEntryList_cb_name, XonoticEntryList_cb_icon;
+void XonoticEntryList_cb(string _name, string _icon) {
+ XonoticEntryList_cb_name = _name;
+ XonoticEntryList_cb_icon = _icon;
+}
+
void XonoticEntryList_drawListBoxItem(entity this, int i, vector absSize, bool isSelected, bool isFocused)
{
if (!this.source) return;
- entity entry = this.source.getEntry(i);
- if (!entry) return;
-
+ if (!this.source.getEntry(i, XonoticEntryList_cb)) return;
+ string name = XonoticEntryList_cb_name;
+ string icon = XonoticEntryList_cb_icon;
if (isSelected) {
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
} else if (isFocused) {
this.focusedItemAlpha = getFadedAlpha(this.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, this.focusedItemAlpha);
}
- string icon = strcat(this.source.entryIconPrefix, entry.(this.source.entryIcon));
- string name = entry.(this.source.entryName);
- string s = draw_TextShortenToWidth(strdecolorize(name), this.columnNameSize, 0, this.realFontSize);
draw_Picture(this.columnPreviewOrigin * eX, icon, this.columnPreviewSize * eX + eY, '1 1 1', SKINALPHA_LISTBOX_SELECTED);
- draw_Text(this.realUpperMargin1 * eY + (this.columnNameOrigin + 0.00 * (this.columnNameSize - draw_TextWidth(s, 0, this.realFontSize))) * eX, s, this.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
+ string s = draw_TextShortenToWidth(strdecolorize(name), this.columnNameSize, 0, this.realFontSize);
+ draw_Text(this.realUpperMargin1 * eY + this.columnNameOrigin * eX, s, this.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
}
float XonoticEntryList_keyDown(entity this, float scan, float ascii, float shift)
{
if (this.nItems <= 0) {
return super.keyDown(this, scan, ascii, shift);
- } else if (scan == K_BACKSPACE) {
- if (time < this.typeToSearchTime) {
- string save = substring(this.typeToSearchString, 0, strlen(this.typeToSearchString) - 1);
- if (this.typeToSearchString) strunzone(this.typeToSearchString);
- this.typeToSearchString = strzone(save);
- this.typeToSearchTime = time + 0.5;
- if (strlen(this.typeToSearchString)) {
- int idx = this.source.indexOf(this.typeToSearchString);
- if (idx >= 0) this.setSelected(this, idx);
- }
+ } else if ((ascii >= 32 || scan == K_BACKSPACE) && this.source.indexOf) {
+ string save;
+ if (scan == K_BACKSPACE) {
+ save = substring(this.typeToSearchString, 0, strlen(this.typeToSearchString) - 1);
+ } else {
+ string ch = chr(ascii);
+ save = (time > this.typeToSearchTime) ? ch : strcat(this.typeToSearchString, ch);
}
- } else if (ascii >= 32 && ascii != 127) {
- string ch = chr(ascii);
- string save = (time > this.typeToSearchTime) ? ch : strcat(this.typeToSearchString, ch);
if (this.typeToSearchString) strunzone(this.typeToSearchString);
this.typeToSearchString = strzone(save);
this.typeToSearchTime = time + 0.5;
- int idx = this.source.indexOf(this.typeToSearchString);
- if (idx >= 0) this.setSelected(this, idx);
+ if (strlen(this.typeToSearchString)) {
+ int idx = this.source.indexOf(this.typeToSearchString);
+ if (idx >= 0) this.setSelected(this, idx);
+ }
} else if (shift & S_CTRL && scan == 'f') {
this.parent.setFocus(this.parent, this.stringFilterBox);
} else if (shift & S_CTRL && scan == 'u') {
}
this.nItems = this.source.reload(this.stringFilter);
for (int i = 0, n = this.nItems; i < n; ++i) {
- draw_PreloadPicture(this.source.getEntry(i).(this.source.entryIcon));
+ if (this.source.getEntry(i, XonoticEntryList_cb)) {
+ draw_PreloadPicture(XonoticEntryList_cb_icon);
+ }
}
}