@@ -31,7 +31,7 @@ class FSO {
3131 return dir;
3232 }
3333 // count entries on folder (files and dirs)
34- idx_t count () {
34+ long count () {
3535 // Serial.print("count:");
3636 dir.rewindDirectory ();
3737 int cnt=0 ;
@@ -49,7 +49,7 @@ class FSO {
4949 }
5050
5151 // get entry index by filename
52- idx_t entryIdx (String name) {
52+ long entryIdx (String name) {
5353 dir.rewindDirectory ();
5454 int cnt=0 ;
5555 while (true ) {
@@ -69,7 +69,7 @@ class FSO {
6969 }
7070
7171 // get folder content entry by index
72- String entry (idx_t idx) {
72+ String entry (long idx) {
7373 dir.rewindDirectory ();
7474 idx_t cnt=0 ;
7575 while (true ) {
@@ -90,6 +90,58 @@ class FSO {
9090
9191};
9292
93+ template <typename SDC,idx_t maxSz>
94+ class CachedFSO :public FSO <SDC> {
95+ public:
96+ using Type=SDC;
97+ long cacheStart=0 ;
98+ String cache[maxSz];
99+ long size=0 ;// folder size (count of files and folders)
100+ CachedFSO (Type& sdc):FSO<SDC>(sdc) {}
101+ void refresh (long start=0 ) {
102+ if (start<0 ) start=0 ;
103+ // Serial.print("Refreshing from:");
104+ // Serial.println(start);
105+ cacheStart=start;
106+ FSO<SDC>::dir.rewindDirectory ();
107+ size=0 ;
108+ while (true ) {
109+ File file=FSO<SDC>::dir.openNextFile ();
110+ if (!file) {
111+ file.close ();
112+ break ;
113+ }
114+ if (start<=size&&size<start+maxSz)
115+ cache[size-start]=String (file.name ())+(file.isDirectory ()?" /" :" " );
116+ file.close ();
117+ size++;
118+ }
119+ }
120+ // open a folder
121+ bool goFolder (String folderName) {
122+ if (!FSO<SDC>::goFolder (folderName)) return false ;
123+ refresh ();
124+ return true ;
125+ }
126+ long count () {return size;}
127+
128+ long entryIdx (String name) {
129+ idx_t sz=min (count (),(long )maxSz);
130+ for (int i=0 ;i<sz;i++)
131+ if (name==cache[i]) return i+cacheStart;
132+ long at=FSO<SDC>::entryIdx (name);
133+ // put cache around the missing item
134+ refresh (at-(maxSz>>1 ));
135+ return at;
136+ }
137+ String entry (long idx) {
138+ if (0 >idx||idx>=size) return " " ;
139+ if (cacheStart<=idx&&idx<(cacheStart+maxSz)) return cache[idx-cacheStart];
140+ refresh (idx-(maxSz>>1 ));
141+ return entry (idx);
142+ }
143+ };
144+
93145// //////////////////////////////////////////////////////////////////////////
94146#include < SD.h>
95147// instead of allocating options for each file we will instead customize a menu
@@ -111,13 +163,7 @@ class SDMenuT:public menuNode,public FS {
111163 :menuNode(title,0 ,NULL ,act,mask,
112164 wrapStyle,(systemStyles)(_menuData|_canNav))
113165 ,FS(sd)
114- // ,sdc(sd)
115- // ,folderName(at)
116- // ,dir(sdc.open(at))
117- {
118- // Serial.println("open dir, construction");
119- // dir=sdc.open(at);
120- }
166+ {}
121167
122168 void begin () {FS::goFolder (folderName);}
123169
@@ -180,13 +226,20 @@ class SDMenuT:public menuNode,public FS {
180226 return out.printRaw (folderName.c_str (),len);
181227 }
182228 // drawing options
183- len-=out.printRaw (SDMenuT<FS>::entry (idx).c_str (),len);
229+ len-=out.printRaw (SDMenuT<FS>::entry (out. tops [root. level ]+ idx).c_str (),len);
184230 return len;
185231 }
186232};
187233
188234class SDMenu :public SDMenuT <FSO<decltype (SD)>> {
189235public:
190236 SDMenu (constText* title,const char * at,Menu::action act=doNothing,Menu::eventMask mask=noEvent)
191- :SDMenuT(SD,title,at,act,mask) {}
237+ :SDMenuT<FSO<decltype (SD)>>(SD,title,at,act,mask) {}
238+ };
239+
240+ template <idx_t cacheSize>
241+ class CachedSDMenu :public SDMenuT <CachedFSO<decltype (SD),cacheSize>> {
242+ public:
243+ CachedSDMenu (constText* title,const char * at,Menu::action act=doNothing,Menu::eventMask mask=noEvent)
244+ :SDMenuT<CachedFSO<decltype (SD),cacheSize>>(SD,title,at,act,mask) {}
192245};
0 commit comments