Jump to content

Exposing scrollbar scroll percentage from C++ to JS


Recommended Posts

Right, so I'm trying to expose how far the scrollbar's scrolled down, so that when it nears the edge, I query the server for more replays. This is part of my project to make a Replay Database for 0ad. Alas, I'm getting this evil error:

WARNING: IGUIObject: setting scrollbar_percentage was not found on an object
ERROR: JavaScript error: gui/rdb/replay_menu.js line 203
Error: Invalid GUIObject property 'scrollbar_percentage'
  onTick@gui/rdb/replay_menu.js:203:1
  __eventhandler125 (tick)@__internal(0) tick:0:1

 

Now, for sake of ease for the reader, I've boiled down my 6k line diff file to these 3 short excerpts, the first a diff file, the second an example of the html used and the final is an example of the js:

Index: binaries/data/mods/mod/gui/gui.rnc
===================================================================
--- binaries/data/mods/mod/gui/gui.rnc	(revision 21928)
+++ binaries/data/mods/mod/gui/gui.rnc	(working copy)
@@ -74,6 +74,7 @@
   attribute offset { pos }?&
   attribute readonly { bool }?&
   attribute scrollbar { bool }?&
+  attribute scrollbar_percentage { xsd:decimal }?&
   attribute scrollbar_style { text }?&
   attribute scroll_bottom { bool }?&
   attribute scroll_top { bool }?&
Index: binaries/data/mods/mod/gui/gui.rng
===================================================================
--- binaries/data/mods/mod/gui/gui.rng	(revision 21928)
+++ binaries/data/mods/mod/gui/gui.rng	(working copy)
@@ -315,6 +315,11 @@
         </attribute>
       </optional>
       <optional>
+        <attribute name="scrollbar_percentage">
+          <data type="decimal"/>
+        </attribute>
+      </optional>
+      <optional>
         <attribute name="scrollbar_style"/>
       </optional>
       <optional>
Index: source/gui/COList.cpp
===================================================================
--- source/gui/COList.cpp	(revision 21928)
+++ source/gui/COList.cpp	(working copy)
@@ -33,6 +33,9 @@
 	AddSetting(GUIST_CGUISpriteInstance,	"sprite_asc");  // Show the order of sorting
 	AddSetting(GUIST_CGUISpriteInstance,	"sprite_desc");
 	AddSetting(GUIST_CGUISpriteInstance,	"sprite_not_sorted");
+	AddSetting(GUIST_float,					"scrollbar_percentage");
+
+	GUI<float>::SetSetting(this, "scrollbar_percentage", 0.0);
 }
 
 void COList::SetupText()
@@ -119,6 +122,14 @@
 		GetScrollBar(0).SetY(rect.top);
 		GetScrollBar(0).SetZ(GetBufferedZ());
 		GetScrollBar(0).SetLength(rect.bottom - rect.top);
+
+        GUI<float>::SetSetting(
+            this,
+            "scrollbar_percentage",
+            GetScrollBar(0).GetMaxPos() == 0
+                ? 1
+                : GetScrollBar(0).GetPos() / GetScrollBar(0).GetMaxPos()
+        );
 	}
 }
 

 

			<object name="replaySelection"
				size="0 35 100% 100%-24"
				type="olist"
				style="ModernSortedList"
				sortable="true"
				selected_column="months"
				selected_column_order="-1"
				font="sans-stroke-13"
				auto_scroll="true"
				scrollbar="true"
			>
				<action on="SelectionChange">displayReplayDetails();</action>
				<action on="SelectionColumnChange">displayReplayList();</action>
				<action on="mouseleftdoubleclickitem">startReplay();</action>

				<!-- Columns -->
				<column id="id" color="172 172 212" width="10%">
					<translatableAttribute id="heading" context="replay">Save Id</translatableAttribute>
				</column>

				<column id="months" color="172 172 212" width="11%">
					<translatableAttribute id="heading" context="replay">Date / Time</translatableAttribute>
				</column>

				<column id="players" color="192 192 192" width="40%">
					<translatableAttribute id="heading" context="replay">Players</translatableAttribute>
				</column>

				<column id="mapName" color="192 192 192" width="12%">
					<translatableAttribute id="heading" context="replay">Map Name</translatableAttribute>
				</column>

				<column id="mapSize" color="192 192 192" width="9%">
					<translatableAttribute id="heading" context="replay">Size</translatableAttribute>
				</column>

				<column id="popCapacity" color="192 192 192" width="9%">
					<translatableAttribute id="heading" context="replay">Population</translatableAttribute>
				</column>

				<column id="duration" color="192 192 192" width="9%">
					<translatableAttribute id="heading" context="replay">Duration</translatableAttribute>
				</column>

			</object>

    if (!g_WaitingForQueryResponce) {
	    var replaySelection = Engine.GetGUIObjectByName("replaySelection");
        if (replaySelection.scrollbar_percentage > 0.9) {
            RdbQueryForReplayList();
            warn("Requery");
        }
    }

 

I've attached the full diff file bellow for those it interests.

0ad-diff

  • Like 2
Link to comment
Share on other sites

We still have some limitations there. We need XML declaration for an attribute to use it in JS (like selected_column_order). Try to add scrollbar_percentage="0.0" to the replaySelection object:

<object name="replaySelection"
	size="0 35 100% 100%-24"
	type="olist"
	style="ModernSortedList"
	sortable="true"
	selected_column="months"
	selected_column_order="-1"
	font="sans-stroke-13"
	auto_scroll="true"
	scrollbar="true"
	scrollbar_percentage="0.0"
>

 

Btw, I can suggest to try use an already existing implementation (ModIo) for the client. Also we put all server/utility stuff in the tools subfolder, because it's not a part of the game.

Link to comment
Share on other sites

3 hours ago, vladislavbelov said:

We still have some limitations there. We need XML declaration for an attribute to use it in JS (like selected_column_order). Try to add scrollbar_percentage="0.0" to the replaySelection object:

Adding `scrollbar_percentage` gives this error:

ERROR: GUI: (object: replaySelection) Can't set "scrollbar_percentage" to "0.0"
TIMER| rdb/replay_menu.xml: 49.1224 ms
WARNING: IGUIObject: setting scrollbar_percentage was not found on an object
ERROR: JavaScript error: gui/rdb/replay_menu.js line 203
Error: Invalid GUIObject property 'scrollbar_percentage'
  onTick@gui/rdb/replay_menu.js:203:1
  __eventhandler64 (tick)@__internal(0) tick:0:1
3 hours ago, vladislavbelov said:

Also we put all server/utility stuff in the tools subfolder, because it's not a part of the game.

Will move.

Link to comment
Share on other sites

3 hours ago, vladislavbelov said:

I removed unrelated things from your patch and tested it. And it works. I attached my version of the patch.

changes_short.patch

That's interesting, with your patch applied on a fresh copy 0ad I'm getting the following:

WARNING: onTick
WARNING: IGUIObject: setting scrollbar_percentage was not found on an object
ERROR: JavaScript error: gui/replaymenu/replay_menu.js line 162
Error: Invalid GUIObject property 'scrollbar_percentage'
  onTick@gui/replaymenu/replay_menu.js:162:2
  __eventhandler45 (tick)@__internal(0) tick:0:1

I used the following commands after getting a fresh copy of 0ad (r21946):

patch -p0 < ~/Downloads/changes_short.patch
cd build/workspaces/
./update-workspaces.sh -j5 --without-tests && cd gcc
make config=debug -j5 && ../../../binaries/system/pyrogenesis

 

Link to comment
Share on other sites

41 minutes ago, gentz said:

used the following commands after getting a fresh copy of 0ad (r21946):


patch -p0 < ~/Downloads/changes_short.patch
cd build/workspaces/
./update-workspaces.sh -j5 --without-tests && cd gcc
make config=debug -j5 && ../../../binaries/system/pyrogenesis

Everything is simpler: you're building debug, but running release. To run debug you need to run the pyrogenesis_dbg :)

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Is loading more data when the scrollbar reached the bottom the nicest solution? Paging would be an alternative. Or displaying everything is made fast enough, which ought to be the case if the cache is always prefilled. Having complete search results also means that one can sort the results.

Link to comment
Share on other sites

On 12/18/2018 at 5:53 AM, elexis said:

Is loading more data when the scrollbar reached the bottom the nicest solution? Paging would be an alternative. Or displaying everything is made fast enough, which ought to be the case if the cache is always prefilled. Having complete search results also means that one can sort the results.

Pages would probably be a better solution, and I'll probably switch to that once the RDB is more feature complete. Currently the server does all the sorting and filtering and just sends the saves over. Sending complete search results would be impractical. Currently each save is ~2kb for the commands and ~15kb for the metadata, the latter being pretty large, so once the weekend comes by I'll start only sending metadata when requested. Currently there is no cache of any sorts.

Edited by gentz
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...