Fossil SCM

On the /timeline page, begin with the "basic" view. Provide an "Advanced" button to fill in details using JS. The "basic" query parameter no longer functions.

drh 2017-11-25 20:43 trunk
Commit 3ede2d874f48467007d8ac5b0c838cf5b0484787e96e3deafac845a9c4bc504a
2 files changed +67 -23 +42 -43
+67 -23
--- src/style.c
+++ src/style.c
@@ -47,21 +47,29 @@
4747
static int nSubmenu = 0; /* Number of buttons */
4848
static struct SubmenuCtrl {
4949
const char *zName; /* Form query parameter */
5050
const char *zLabel; /* Label. Might be NULL for FF_MULTI */
5151
unsigned char eType; /* FF_ENTRY, FF_MULTI, FF_BINARY */
52
- unsigned char isDisabled; /* True if this control is grayed out */
52
+ unsigned char eVisible; /* STYLE_NORMAL, STYLE_VISIBLE, .... */
5353
short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
5454
const char *const *azChoice; /* value/display pairs for FF_MULTI */
5555
const char *zFalse; /* FF_BINARY label when false */
5656
const char *zJS; /* Javascript to run on toggle */
5757
} aSubmenuCtrl[20];
5858
static int nSubmenuCtrl = 0;
59
-#define FF_ENTRY 1
60
-#define FF_MULTI 2
61
-#define FF_BINARY 3
62
-#define FF_CHECKBOX 4
59
+#define FF_ENTRY 1 /* Text entry box */
60
+#define FF_MULTI 2 /* Combobox. Multiple choices. */
61
+#define FF_BINARY 3 /* Control binary query parameter */
62
+#define FF_CHECKBOX 4 /* Check-box with JS */
63
+#define FF_JSBUTTON 5 /* Run JS when clicked */
64
+
65
+#if INTERFACE
66
+#define STYLE_NORMAL 0 /* Normal display of control */
67
+#define STYLE_DISABLED 1 /* Control is disabled */
68
+#define STYLE_CLUTTER 2 /* Only visible in "Advanced" display */
69
+#define STYLE_BASIC 4 /* Only visible in "Basic" display */
70
+#endif /* INTERFACE */
6371
6472
/*
6573
** Remember that the header has been generated. The footer is omitted
6674
** if an error occurs before the header.
6775
*/
@@ -248,59 +256,71 @@
248256
}
249257
void style_submenu_entry(
250258
const char *zName, /* Query parameter name */
251259
const char *zLabel, /* Label before the entry box */
252260
int iSize, /* Size of the entry box */
253
- int isDisabled /* True if disabled */
261
+ int eVisible /* Visible or disabled */
254262
){
255263
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
256264
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
257265
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
258266
aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
259
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
267
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
260268
aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
261269
nSubmenuCtrl++;
262270
}
263271
void style_submenu_checkbox(
264272
const char *zName, /* Query parameter name */
265273
const char *zLabel, /* Label to display after the checkbox */
266
- int isDisabled, /* True if disabled */
274
+ int eVisible, /* Visible or disabled */
267275
const char *zJS /* Optional javascript to run on toggle */
268276
){
269277
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
270278
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
271279
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
272
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
280
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
273281
aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
274282
aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX;
275283
nSubmenuCtrl++;
284
+}
285
+void style_submenu_jsbutton(
286
+ const char *zLabel, /* Label to display on the submenu */
287
+ int eVisible, /* Visible or disabled */
288
+ const char *zJS /* Javascript to run when clicked */
289
+){
290
+ assert( nSubmenuCtrl < count(aSubmenuCtrl) );
291
+ aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
292
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
293
+ aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
294
+ aSubmenuCtrl[nSubmenuCtrl].eType = FF_JSBUTTON;
295
+ nSubmenuCtrl++;
276296
}
277297
void style_submenu_binary(
278298
const char *zName, /* Query parameter name */
279299
const char *zTrue, /* Label to show when parameter is true */
280300
const char *zFalse, /* Label to show when the parameter is false */
281
- int isDisabled /* True if this control is disabled */
301
+ int eVisible /* Visible or disabled */
282302
){
283303
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
284304
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
285305
aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
286306
aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
287
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
307
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
288308
aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
289309
nSubmenuCtrl++;
290310
}
291311
void style_submenu_multichoice(
292
- const char *zName, /* Query parameter name */
293
- int nChoice, /* Number of options */
294
- const char *const *azChoice,/* value/display pairs. 2*nChoice entries */
295
- int isDisabled /* True if this control is disabled */
312
+ const char *zName, /* Query parameter name */
313
+ int nChoice, /* Number of options */
314
+ const char *const *azChoice, /* value/display pairs. 2*nChoice entries */
315
+ int eVisible /* Visible or disabled */
296316
){
297317
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
298318
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
299319
aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
300320
aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
301
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
321
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
302322
aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
303323
nSubmenuCtrl++;
304324
}
305325
void style_submenu_sql(
306326
const char *zName, /* Query parameter name */
@@ -329,11 +349,11 @@
329349
if( n>0 ){
330350
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
331351
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
332352
aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
333353
aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
334
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0;
354
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL;
335355
aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
336356
nSubmenuCtrl++;
337357
}
338358
}
339359
@@ -563,18 +583,26 @@
563583
}
564584
}
565585
}
566586
for(i=0; i<nSubmenuCtrl; i++){
567587
const char *zQPN = aSubmenuCtrl[i].zName;
568
- const char *zDisabled = " disabled";
569
- if( !aSubmenuCtrl[i].isDisabled ){
570
- zDisabled = "";
588
+ const char *zDisabled = "";
589
+ const char *zXtraClass = "";
590
+ if( aSubmenuCtrl[i].eVisible & STYLE_DISABLED ){
591
+ zDisabled = " disabled";
592
+ }else if( zQPN ){
571593
cgi_tag_query_parameter(zQPN);
594
+ }
595
+ if( aSubmenuCtrl[i].eVisible & STYLE_CLUTTER ){
596
+ zXtraClass = " clutter";
597
+ }
598
+ if( aSubmenuCtrl[i].eVisible & STYLE_BASIC ){
599
+ zXtraClass = " anticlutter";
572600
}
573601
switch( aSubmenuCtrl[i].eType ){
574602
case FF_ENTRY:
575
- @ <span class='submenuctrl'>\
603
+ @ <span class='submenuctrl%s(zXtraClass)'>\
576604
@ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
577605
@ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
578606
if( aSubmenuCtrl[i].iSize<0 ){
579607
@ size='%d(-aSubmenuCtrl[i].iSize)' \
580608
}else if( aSubmenuCtrl[i].iSize>0 ){
@@ -584,10 +612,13 @@
584612
@ onchange='gebi("f01").submit();'%s(zDisabled)></span>
585613
break;
586614
case FF_MULTI: {
587615
int j;
588616
const char *zVal = P(zQPN);
617
+ if( zXtraClass[0] ){
618
+ @ <span class='%s(zXtraClass+1)'>
619
+ }
589620
if( aSubmenuCtrl[i].zLabel ){
590621
@ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
591622
}
592623
@ <select class='submenuctrl' size='1' name='%s(zQPN)' \
593624
@ onchange='gebi("f01").submit();'%s(zDisabled)>
@@ -598,15 +629,18 @@
598629
@ selected\
599630
}
600631
@ >%h(aSubmenuCtrl[i].azChoice[j+1])</option>
601632
}
602633
@ </select>
634
+ if( zXtraClass[0] ){
635
+ @ </span>
636
+ }
603637
break;
604638
}
605639
case FF_BINARY: {
606640
int isTrue = PB(zQPN);
607
- @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
641
+ @ <select class='submenuctrl%s(zXtraClass)' size='1' name='%s(zQPN)' \
608642
@ onchange='gebi("f01").submit();'%s(zDisabled)>
609643
@ <option value='1'\
610644
if( isTrue ){
611645
@ selected\
612646
}
@@ -618,11 +652,11 @@
618652
@ >%h(aSubmenuCtrl[i].zFalse)</option>
619653
@ </select>
620654
break;
621655
}
622656
case FF_CHECKBOX: {
623
- @ <label class='submenuctrl submenuckbox'>\
657
+ @ <label class='submenuctrl submenuckbox%s(zXtraClass)'>\
624658
@ <input type='checkbox' name='%s(zQPN)' \
625659
if( PB(zQPN) ){
626660
@ checked \
627661
}
628662
if( aSubmenuCtrl[i].zJS ){
@@ -630,10 +664,16 @@
630664
}else{
631665
@ onchange='gebi("f01").submit();'%s(zDisabled)>\
632666
}
633667
@ %h(aSubmenuCtrl[i].zLabel)</label>
634668
break;
669
+ }
670
+ case FF_JSBUTTON: {
671
+ @ <a class="label%s(zXtraClass)" \
672
+ @ onclick='%s(aSubmenuCtrl[i].zJS)'%s(zDisabled)>\
673
+ @ %s(aSubmenuCtrl[i].zLabel)</a>
674
+ break;
635675
}
636676
}
637677
}
638678
@ </div>
639679
if( nSubmenuCtrl ){
@@ -1492,10 +1532,14 @@
14921532
},
14931533
{ "p.searchEmpty",
14941534
"Message explaining that there are no search results",
14951535
@ font-style: italic;
14961536
},
1537
+ { ".clutter",
1538
+ "Detail screen objects",
1539
+ @ display: none;
1540
+ },
14971541
{ 0,
14981542
0,
14991543
0
15001544
}
15011545
};
15021546
--- src/style.c
+++ src/style.c
@@ -47,21 +47,29 @@
47 static int nSubmenu = 0; /* Number of buttons */
48 static struct SubmenuCtrl {
49 const char *zName; /* Form query parameter */
50 const char *zLabel; /* Label. Might be NULL for FF_MULTI */
51 unsigned char eType; /* FF_ENTRY, FF_MULTI, FF_BINARY */
52 unsigned char isDisabled; /* True if this control is grayed out */
53 short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
54 const char *const *azChoice; /* value/display pairs for FF_MULTI */
55 const char *zFalse; /* FF_BINARY label when false */
56 const char *zJS; /* Javascript to run on toggle */
57 } aSubmenuCtrl[20];
58 static int nSubmenuCtrl = 0;
59 #define FF_ENTRY 1
60 #define FF_MULTI 2
61 #define FF_BINARY 3
62 #define FF_CHECKBOX 4
 
 
 
 
 
 
 
 
63
64 /*
65 ** Remember that the header has been generated. The footer is omitted
66 ** if an error occurs before the header.
67 */
@@ -248,59 +256,71 @@
248 }
249 void style_submenu_entry(
250 const char *zName, /* Query parameter name */
251 const char *zLabel, /* Label before the entry box */
252 int iSize, /* Size of the entry box */
253 int isDisabled /* True if disabled */
254 ){
255 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
256 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
257 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
258 aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
259 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
260 aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
261 nSubmenuCtrl++;
262 }
263 void style_submenu_checkbox(
264 const char *zName, /* Query parameter name */
265 const char *zLabel, /* Label to display after the checkbox */
266 int isDisabled, /* True if disabled */
267 const char *zJS /* Optional javascript to run on toggle */
268 ){
269 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
270 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
271 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
272 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
273 aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
274 aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX;
275 nSubmenuCtrl++;
 
 
 
 
 
 
 
 
 
 
 
 
276 }
277 void style_submenu_binary(
278 const char *zName, /* Query parameter name */
279 const char *zTrue, /* Label to show when parameter is true */
280 const char *zFalse, /* Label to show when the parameter is false */
281 int isDisabled /* True if this control is disabled */
282 ){
283 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
284 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
285 aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
286 aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
287 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
288 aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
289 nSubmenuCtrl++;
290 }
291 void style_submenu_multichoice(
292 const char *zName, /* Query parameter name */
293 int nChoice, /* Number of options */
294 const char *const *azChoice,/* value/display pairs. 2*nChoice entries */
295 int isDisabled /* True if this control is disabled */
296 ){
297 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
298 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
299 aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
300 aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
301 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
302 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
303 nSubmenuCtrl++;
304 }
305 void style_submenu_sql(
306 const char *zName, /* Query parameter name */
@@ -329,11 +349,11 @@
329 if( n>0 ){
330 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
331 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
332 aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
333 aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
334 aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0;
335 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
336 nSubmenuCtrl++;
337 }
338 }
339
@@ -563,18 +583,26 @@
563 }
564 }
565 }
566 for(i=0; i<nSubmenuCtrl; i++){
567 const char *zQPN = aSubmenuCtrl[i].zName;
568 const char *zDisabled = " disabled";
569 if( !aSubmenuCtrl[i].isDisabled ){
570 zDisabled = "";
 
 
571 cgi_tag_query_parameter(zQPN);
 
 
 
 
 
 
572 }
573 switch( aSubmenuCtrl[i].eType ){
574 case FF_ENTRY:
575 @ <span class='submenuctrl'>\
576 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
577 @ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
578 if( aSubmenuCtrl[i].iSize<0 ){
579 @ size='%d(-aSubmenuCtrl[i].iSize)' \
580 }else if( aSubmenuCtrl[i].iSize>0 ){
@@ -584,10 +612,13 @@
584 @ onchange='gebi("f01").submit();'%s(zDisabled)></span>
585 break;
586 case FF_MULTI: {
587 int j;
588 const char *zVal = P(zQPN);
 
 
 
589 if( aSubmenuCtrl[i].zLabel ){
590 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
591 }
592 @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
593 @ onchange='gebi("f01").submit();'%s(zDisabled)>
@@ -598,15 +629,18 @@
598 @ selected\
599 }
600 @ >%h(aSubmenuCtrl[i].azChoice[j+1])</option>
601 }
602 @ </select>
 
 
 
603 break;
604 }
605 case FF_BINARY: {
606 int isTrue = PB(zQPN);
607 @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
608 @ onchange='gebi("f01").submit();'%s(zDisabled)>
609 @ <option value='1'\
610 if( isTrue ){
611 @ selected\
612 }
@@ -618,11 +652,11 @@
618 @ >%h(aSubmenuCtrl[i].zFalse)</option>
619 @ </select>
620 break;
621 }
622 case FF_CHECKBOX: {
623 @ <label class='submenuctrl submenuckbox'>\
624 @ <input type='checkbox' name='%s(zQPN)' \
625 if( PB(zQPN) ){
626 @ checked \
627 }
628 if( aSubmenuCtrl[i].zJS ){
@@ -630,10 +664,16 @@
630 }else{
631 @ onchange='gebi("f01").submit();'%s(zDisabled)>\
632 }
633 @ %h(aSubmenuCtrl[i].zLabel)</label>
634 break;
 
 
 
 
 
 
635 }
636 }
637 }
638 @ </div>
639 if( nSubmenuCtrl ){
@@ -1492,10 +1532,14 @@
1492 },
1493 { "p.searchEmpty",
1494 "Message explaining that there are no search results",
1495 @ font-style: italic;
1496 },
 
 
 
 
1497 { 0,
1498 0,
1499 0
1500 }
1501 };
1502
--- src/style.c
+++ src/style.c
@@ -47,21 +47,29 @@
47 static int nSubmenu = 0; /* Number of buttons */
48 static struct SubmenuCtrl {
49 const char *zName; /* Form query parameter */
50 const char *zLabel; /* Label. Might be NULL for FF_MULTI */
51 unsigned char eType; /* FF_ENTRY, FF_MULTI, FF_BINARY */
52 unsigned char eVisible; /* STYLE_NORMAL, STYLE_VISIBLE, .... */
53 short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
54 const char *const *azChoice; /* value/display pairs for FF_MULTI */
55 const char *zFalse; /* FF_BINARY label when false */
56 const char *zJS; /* Javascript to run on toggle */
57 } aSubmenuCtrl[20];
58 static int nSubmenuCtrl = 0;
59 #define FF_ENTRY 1 /* Text entry box */
60 #define FF_MULTI 2 /* Combobox. Multiple choices. */
61 #define FF_BINARY 3 /* Control binary query parameter */
62 #define FF_CHECKBOX 4 /* Check-box with JS */
63 #define FF_JSBUTTON 5 /* Run JS when clicked */
64
65 #if INTERFACE
66 #define STYLE_NORMAL 0 /* Normal display of control */
67 #define STYLE_DISABLED 1 /* Control is disabled */
68 #define STYLE_CLUTTER 2 /* Only visible in "Advanced" display */
69 #define STYLE_BASIC 4 /* Only visible in "Basic" display */
70 #endif /* INTERFACE */
71
72 /*
73 ** Remember that the header has been generated. The footer is omitted
74 ** if an error occurs before the header.
75 */
@@ -248,59 +256,71 @@
256 }
257 void style_submenu_entry(
258 const char *zName, /* Query parameter name */
259 const char *zLabel, /* Label before the entry box */
260 int iSize, /* Size of the entry box */
261 int eVisible /* Visible or disabled */
262 ){
263 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
264 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
265 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
266 aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
267 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
268 aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
269 nSubmenuCtrl++;
270 }
271 void style_submenu_checkbox(
272 const char *zName, /* Query parameter name */
273 const char *zLabel, /* Label to display after the checkbox */
274 int eVisible, /* Visible or disabled */
275 const char *zJS /* Optional javascript to run on toggle */
276 ){
277 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
278 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
279 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
280 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
281 aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
282 aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX;
283 nSubmenuCtrl++;
284 }
285 void style_submenu_jsbutton(
286 const char *zLabel, /* Label to display on the submenu */
287 int eVisible, /* Visible or disabled */
288 const char *zJS /* Javascript to run when clicked */
289 ){
290 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
291 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
292 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
293 aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
294 aSubmenuCtrl[nSubmenuCtrl].eType = FF_JSBUTTON;
295 nSubmenuCtrl++;
296 }
297 void style_submenu_binary(
298 const char *zName, /* Query parameter name */
299 const char *zTrue, /* Label to show when parameter is true */
300 const char *zFalse, /* Label to show when the parameter is false */
301 int eVisible /* Visible or disabled */
302 ){
303 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
304 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
305 aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
306 aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
307 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
308 aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
309 nSubmenuCtrl++;
310 }
311 void style_submenu_multichoice(
312 const char *zName, /* Query parameter name */
313 int nChoice, /* Number of options */
314 const char *const *azChoice, /* value/display pairs. 2*nChoice entries */
315 int eVisible /* Visible or disabled */
316 ){
317 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
318 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
319 aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
320 aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
321 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
322 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
323 nSubmenuCtrl++;
324 }
325 void style_submenu_sql(
326 const char *zName, /* Query parameter name */
@@ -329,11 +349,11 @@
349 if( n>0 ){
350 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
351 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
352 aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
353 aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
354 aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL;
355 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
356 nSubmenuCtrl++;
357 }
358 }
359
@@ -563,18 +583,26 @@
583 }
584 }
585 }
586 for(i=0; i<nSubmenuCtrl; i++){
587 const char *zQPN = aSubmenuCtrl[i].zName;
588 const char *zDisabled = "";
589 const char *zXtraClass = "";
590 if( aSubmenuCtrl[i].eVisible & STYLE_DISABLED ){
591 zDisabled = " disabled";
592 }else if( zQPN ){
593 cgi_tag_query_parameter(zQPN);
594 }
595 if( aSubmenuCtrl[i].eVisible & STYLE_CLUTTER ){
596 zXtraClass = " clutter";
597 }
598 if( aSubmenuCtrl[i].eVisible & STYLE_BASIC ){
599 zXtraClass = " anticlutter";
600 }
601 switch( aSubmenuCtrl[i].eType ){
602 case FF_ENTRY:
603 @ <span class='submenuctrl%s(zXtraClass)'>\
604 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
605 @ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
606 if( aSubmenuCtrl[i].iSize<0 ){
607 @ size='%d(-aSubmenuCtrl[i].iSize)' \
608 }else if( aSubmenuCtrl[i].iSize>0 ){
@@ -584,10 +612,13 @@
612 @ onchange='gebi("f01").submit();'%s(zDisabled)></span>
613 break;
614 case FF_MULTI: {
615 int j;
616 const char *zVal = P(zQPN);
617 if( zXtraClass[0] ){
618 @ <span class='%s(zXtraClass+1)'>
619 }
620 if( aSubmenuCtrl[i].zLabel ){
621 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
622 }
623 @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
624 @ onchange='gebi("f01").submit();'%s(zDisabled)>
@@ -598,15 +629,18 @@
629 @ selected\
630 }
631 @ >%h(aSubmenuCtrl[i].azChoice[j+1])</option>
632 }
633 @ </select>
634 if( zXtraClass[0] ){
635 @ </span>
636 }
637 break;
638 }
639 case FF_BINARY: {
640 int isTrue = PB(zQPN);
641 @ <select class='submenuctrl%s(zXtraClass)' size='1' name='%s(zQPN)' \
642 @ onchange='gebi("f01").submit();'%s(zDisabled)>
643 @ <option value='1'\
644 if( isTrue ){
645 @ selected\
646 }
@@ -618,11 +652,11 @@
652 @ >%h(aSubmenuCtrl[i].zFalse)</option>
653 @ </select>
654 break;
655 }
656 case FF_CHECKBOX: {
657 @ <label class='submenuctrl submenuckbox%s(zXtraClass)'>\
658 @ <input type='checkbox' name='%s(zQPN)' \
659 if( PB(zQPN) ){
660 @ checked \
661 }
662 if( aSubmenuCtrl[i].zJS ){
@@ -630,10 +664,16 @@
664 }else{
665 @ onchange='gebi("f01").submit();'%s(zDisabled)>\
666 }
667 @ %h(aSubmenuCtrl[i].zLabel)</label>
668 break;
669 }
670 case FF_JSBUTTON: {
671 @ <a class="label%s(zXtraClass)" \
672 @ onclick='%s(aSubmenuCtrl[i].zJS)'%s(zDisabled)>\
673 @ %s(aSubmenuCtrl[i].zLabel)</a>
674 break;
675 }
676 }
677 }
678 @ </div>
679 if( nSubmenuCtrl ){
@@ -1492,10 +1532,14 @@
1532 },
1533 { "p.searchEmpty",
1534 "Message explaining that there are no search results",
1535 @ font-style: italic;
1536 },
1537 { ".clutter",
1538 "Detail screen objects",
1539 @ display: none;
1540 },
1541 { 0,
1542 0,
1543 0
1544 }
1545 };
1546
+42 -43
--- src/timeline.c
+++ src/timeline.c
@@ -103,11 +103,10 @@
103103
#define TIMELINE_UCOLOR 0x0080 /* Background color by user */
104104
#define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
105105
#define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
106106
#define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
107107
#define TIMELINE_BISECT 0x0800 /* Show supplimental bisect information */
108
-#define TIMELINE_BASIC 0x1000 /* Minimize clutter and distraction */
109108
#endif
110109
111110
/*
112111
** Hash a string and use the hash to determine a background color.
113112
*/
@@ -265,19 +264,17 @@
265264
}
266265
zPrevDate[0] = 0;
267266
mxWikiLen = db_get_int("timeline-max-comment", 0);
268267
dateFormat = db_get_int("timeline-date-format", 0);
269268
bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
270
- if( tmFlags & TIMELINE_BASIC ){
271
- eCommentFormat = 5; /* Comment only */
272
- }else{
269
+ {
273270
/* Undocumented query parameter commentformat=N takes a numeric parameter to
274271
** adjust the comment-format for testing purposes. */
275272
const char *z = P("commentformat");
276273
eCommentFormat = z ? atoi(z) : db_get_int("timeline-comment-format", 0);
277274
}
278
- bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
275
+ bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
279276
bSeparateDetail = (eCommentFormat & 8)!=0; /* Bit 3 turns on the detail column */
280277
switch( (eCommentFormat>>1)&3 ){
281278
case 1: bHashAfterComment = 1; break;
282279
case 2: bHashInDetail = 1; break;
283280
default: bHashBeforeComment = 1; break;
@@ -565,10 +562,11 @@
565562
@ style="background-color: %h(zBgClr);">
566563
}else{
567564
@ <td class="timelineTableCell timelineDetailCell">
568565
}
569566
}
567
+ cgi_printf("<span class='clutter'>");
570568
if( zType[0]=='c' ){
571569
cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
572570
}else{
573571
cgi_printf("<span class='timelineDetail'>(");
574572
}
@@ -638,11 +636,11 @@
638636
cgi_printf(" id: %d&larr;%d", rid, srcId);
639637
}else{
640638
cgi_printf(" id: %d", rid);
641639
}
642640
}
643
- cgi_printf(")</span>\n"); /* End of the details section */
641
+ cgi_printf(")</span></span>\n"); /* End of the details section */
644642
}
645643
646644
tag_private_status(rid);
647645
648646
/* Generate extra hyperlinks at the end of the comment */
@@ -814,11 +812,11 @@
814812
iRailPitch = atoi(PD("railpitch","0"));
815813
showArrowheads = skin_detail_boolean("timeline-arrowheads");
816814
circleNodes = skin_detail_boolean("timeline-circle-nodes");
817815
colorGraph = skin_detail_boolean("timeline-color-graph-lines");
818816
819
- @ <script>(function(){
817
+ @ <script>
820818
@ "use strict";
821819
@ var css = "";
822820
if( circleNodes ){
823821
@ css += ".tl-node, .tl-node:after { border-radius: 50%%; }";
824822
}
@@ -1141,10 +1139,25 @@
11411139
}else{
11421140
@ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1";
11431141
}
11441142
}
11451143
@ }
1144
+ @ }
1145
+ @ function changeDisplay(selector,value){
1146
+ @ var x = document.getElementsByClassName(selector);
1147
+ @ var n = x.length;
1148
+ @ for(var i=0; i<n; i++) {x[i].style.display = value;}
1149
+ @ }
1150
+ @ function declutter(){
1151
+ @ changeDisplay('clutter','none');
1152
+ @ changeDisplay('anticlutter','inline');
1153
+ @ checkHeight();
1154
+ @ }
1155
+ @ function reclutter(){
1156
+ @ changeDisplay('clutter','inline');
1157
+ @ changeDisplay('anticlutter','none');
1158
+ @ checkHeight();
11461159
@ }
11471160
@ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id);
11481161
@ var lastY = 0;
11491162
@ function checkHeight(){
11501163
@ var h = absoluteY(lastRow);
@@ -1154,11 +1167,11 @@
11541167
@ }
11551168
@ setTimeout(checkHeight, 1000);
11561169
@ }
11571170
@ initGraph();
11581171
@ checkHeight();
1159
- @ }())</script>
1172
+ @ </script>
11601173
}
11611174
}
11621175
11631176
/*
11641177
** Create a temporary table suitable for storing timeline data.
@@ -1324,11 +1337,11 @@
13241337
az[i++] = "Wiki";
13251338
}
13261339
assert( i<=count(az) );
13271340
}
13281341
if( i>2 ){
1329
- style_submenu_multichoice("y", i/2, az, isDisabled);
1342
+ style_submenu_multichoice("y", i/2, az, isDisabled|STYLE_CLUTTER);
13301343
}
13311344
}
13321345
13331346
/*
13341347
** If the zChng string is not NULL, then it should be a comma-separated
@@ -1574,11 +1587,10 @@
15741587
/*
15751588
** WEBPAGE: timeline
15761589
**
15771590
** Query parameters:
15781591
**
1579
-** basic Minimum clutter and distraction
15801592
** a=TIMEORTAG After this event
15811593
** b=TIMEORTAG Before this event
15821594
** c=TIMEORTAG "Circa" this event
15831595
** m=TIMEORTAG Mark this event
15841596
** n=COUNT Suggested number of events in output
@@ -1626,12 +1638,11 @@
16261638
int nEntry; /* Max number of entries on timeline */
16271639
int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
16281640
int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
16291641
int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
16301642
const char *zUser = P("u"); /* All entries by this user if not NULL */
1631
- int bBasic = PB("basic"); /* Minimize clutter and distraction */
1632
- const char *zType = PD("y",bBasic?"ci":"all"); /* Type of events. All if NULL */
1643
+ const char *zType = PD("y","all"); /* Type of events. All if NULL */
16331644
const char *zAfter = P("a"); /* Events after this time */
16341645
const char *zBefore = P("b"); /* Events before this time */
16351646
const char *zCirca = P("c"); /* Events near this time */
16361647
const char *zMark = P("m"); /* Mark this event or an event this time */
16371648
const char *zTagName = P("t"); /* Show events with this tag */
@@ -1732,11 +1743,11 @@
17321743
/* For exact maching, inhibit links to the selected tag. */
17331744
zThisTag = zTagName;
17341745
}
17351746
17361747
/* Display a checkbox to enable/disable display of related check-ins. */
1737
- if( !bBasic ) style_submenu_checkbox("rel", "Related", 0, 0);
1748
+ style_submenu_checkbox("rel", "Related", STYLE_CLUTTER, 0);
17381749
17391750
/* Construct the tag match expression. */
17401751
zTagSql = tagMatchExpression(matchStyle, zTagName, &zMatchDesc, &zError);
17411752
}
17421753
@@ -1864,13 +1875,11 @@
18641875
blob_append(&sql, ")", -1);
18651876
path_reset();
18661877
addFileGlobExclusion(zChng, &sql);
18671878
tmFlags |= TIMELINE_DISJOINT;
18681879
db_multi_exec("%s", blob_sql_text(&sql));
1869
- if( !bBasic ){
1870
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1871
- }
1880
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
18721881
blob_appendf(&desc, "%d check-ins going from ",
18731882
db_int(0, "SELECT count(*) FROM timeline"));
18741883
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
18751884
blob_append(&desc, " to ", -1);
18761885
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1916,15 +1925,13 @@
19161925
if( p_rid ){
19171926
/* If both p= and d= are set, we don't have the uuid of d yet. */
19181927
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
19191928
}
19201929
}
1921
- if( !bBasic ){
1922
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1923
- style_submenu_entry("n","Max:",4,0);
1924
- timeline_y_submenu(1);
1925
- }
1930
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
1931
+ style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
1932
+ timeline_y_submenu(1);
19261933
}else if( f_rid && g.perm.Read ){
19271934
/* If f= is present, ignore all other parameters other than n= */
19281935
char *zUuid;
19291936
db_multi_exec(
19301937
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1938,14 +1945,12 @@
19381945
if( useDividers ) selectedRid = f_rid;
19391946
blob_appendf(&desc, "Parents and children of check-in ");
19401947
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
19411948
blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
19421949
tmFlags |= TIMELINE_DISJOINT;
1943
- if( !bBasic ){
1944
- style_submenu_checkbox("unhide", "Unhide", 0, 0);
1945
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1946
- }
1950
+ style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
1951
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
19471952
}else{
19481953
/* Otherwise, a timeline based on a span of time */
19491954
int n;
19501955
const char *zEType = "timeline item";
19511956
char *zDate;
@@ -2225,34 +2230,29 @@
22252230
/* timeline_submenu(&url, "Newer", "a", zDate, "b"); */
22262231
zNewerButton = fossil_strdup(url_render(&url, "a", zDate, "b", 0));
22272232
}
22282233
free(zDate);
22292234
}
2230
- if( !bBasic ){
2231
- if( zType[0]=='a' || zType[0]=='c' ){
2232
- style_submenu_checkbox("unhide", "Unhide", 0, 0);
2233
- }
2234
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
2235
- style_submenu_entry("n","Max:",4,0);
2236
- timeline_y_submenu(disableY);
2237
- style_submenu_entry("t", "Tag Filter:", -8, 0);
2238
- style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, 0);
2239
- }
2240
- }
2241
- blob_zero(&cond);
2242
- }
2243
- if( bBasic ){
2244
- timeline_submenu(&url, "Details", "basic", 0, 0);
2245
- }else{
2246
- timeline_submenu(&url, "Declutter", "basic", "1", 0);
2235
+ if( zType[0]=='a' || zType[0]=='c' ){
2236
+ style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
2237
+ }
2238
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
2239
+ style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
2240
+ timeline_y_submenu(disableY);
2241
+ style_submenu_entry("t", "Tag Filter:", -8, STYLE_CLUTTER);
2242
+ style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, STYLE_CLUTTER);
2243
+ }
2244
+ blob_zero(&cond);
22472245
}
22482246
if( PB("showsql") ){
22492247
@ <pre>%h(blob_sql_text(&sql))</pre>
22502248
}
22512249
if( search_restrict(SRCH_CKIN)!=0 ){
22522250
style_submenu_element("Search", "%R/search?y=c");
22532251
}
2252
+ style_submenu_jsbutton("Advanced", STYLE_BASIC, "reclutter()");
2253
+ style_submenu_jsbutton("Basic", STYLE_CLUTTER, "declutter()");
22542254
if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
22552255
if( useDividers && zMark && zMark[0] ){
22562256
double r = symbolic_name_to_mtime(zMark);
22572257
if( r>0.0 ) selectedRid = timeline_add_divider(r);
22582258
}
@@ -2263,11 +2263,10 @@
22632263
22642264
/* Report any errors. */
22652265
if( zError ){
22662266
@ <p class="generalError">%h(zError)</p>
22672267
}
2268
- if( bBasic ) tmFlags |= TIMELINE_BASIC;
22692268
22702269
if( zNewerButton ){
22712270
@ %z(xhref("class='button'","%z",zNewerButton))More&nbsp;&uarr;</a>
22722271
}
22732272
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, selectedRid, 0);
22742273
--- src/timeline.c
+++ src/timeline.c
@@ -103,11 +103,10 @@
103 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
104 #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
105 #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
106 #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
107 #define TIMELINE_BISECT 0x0800 /* Show supplimental bisect information */
108 #define TIMELINE_BASIC 0x1000 /* Minimize clutter and distraction */
109 #endif
110
111 /*
112 ** Hash a string and use the hash to determine a background color.
113 */
@@ -265,19 +264,17 @@
265 }
266 zPrevDate[0] = 0;
267 mxWikiLen = db_get_int("timeline-max-comment", 0);
268 dateFormat = db_get_int("timeline-date-format", 0);
269 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
270 if( tmFlags & TIMELINE_BASIC ){
271 eCommentFormat = 5; /* Comment only */
272 }else{
273 /* Undocumented query parameter commentformat=N takes a numeric parameter to
274 ** adjust the comment-format for testing purposes. */
275 const char *z = P("commentformat");
276 eCommentFormat = z ? atoi(z) : db_get_int("timeline-comment-format", 0);
277 }
278 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
279 bSeparateDetail = (eCommentFormat & 8)!=0; /* Bit 3 turns on the detail column */
280 switch( (eCommentFormat>>1)&3 ){
281 case 1: bHashAfterComment = 1; break;
282 case 2: bHashInDetail = 1; break;
283 default: bHashBeforeComment = 1; break;
@@ -565,10 +562,11 @@
565 @ style="background-color: %h(zBgClr);">
566 }else{
567 @ <td class="timelineTableCell timelineDetailCell">
568 }
569 }
 
570 if( zType[0]=='c' ){
571 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
572 }else{
573 cgi_printf("<span class='timelineDetail'>(");
574 }
@@ -638,11 +636,11 @@
638 cgi_printf(" id: %d&larr;%d", rid, srcId);
639 }else{
640 cgi_printf(" id: %d", rid);
641 }
642 }
643 cgi_printf(")</span>\n"); /* End of the details section */
644 }
645
646 tag_private_status(rid);
647
648 /* Generate extra hyperlinks at the end of the comment */
@@ -814,11 +812,11 @@
814 iRailPitch = atoi(PD("railpitch","0"));
815 showArrowheads = skin_detail_boolean("timeline-arrowheads");
816 circleNodes = skin_detail_boolean("timeline-circle-nodes");
817 colorGraph = skin_detail_boolean("timeline-color-graph-lines");
818
819 @ <script>(function(){
820 @ "use strict";
821 @ var css = "";
822 if( circleNodes ){
823 @ css += ".tl-node, .tl-node:after { border-radius: 50%%; }";
824 }
@@ -1141,10 +1139,25 @@
1141 }else{
1142 @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1";
1143 }
1144 }
1145 @ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1146 @ }
1147 @ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id);
1148 @ var lastY = 0;
1149 @ function checkHeight(){
1150 @ var h = absoluteY(lastRow);
@@ -1154,11 +1167,11 @@
1154 @ }
1155 @ setTimeout(checkHeight, 1000);
1156 @ }
1157 @ initGraph();
1158 @ checkHeight();
1159 @ }())</script>
1160 }
1161 }
1162
1163 /*
1164 ** Create a temporary table suitable for storing timeline data.
@@ -1324,11 +1337,11 @@
1324 az[i++] = "Wiki";
1325 }
1326 assert( i<=count(az) );
1327 }
1328 if( i>2 ){
1329 style_submenu_multichoice("y", i/2, az, isDisabled);
1330 }
1331 }
1332
1333 /*
1334 ** If the zChng string is not NULL, then it should be a comma-separated
@@ -1574,11 +1587,10 @@
1574 /*
1575 ** WEBPAGE: timeline
1576 **
1577 ** Query parameters:
1578 **
1579 ** basic Minimum clutter and distraction
1580 ** a=TIMEORTAG After this event
1581 ** b=TIMEORTAG Before this event
1582 ** c=TIMEORTAG "Circa" this event
1583 ** m=TIMEORTAG Mark this event
1584 ** n=COUNT Suggested number of events in output
@@ -1626,12 +1638,11 @@
1626 int nEntry; /* Max number of entries on timeline */
1627 int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
1628 int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
1629 int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
1630 const char *zUser = P("u"); /* All entries by this user if not NULL */
1631 int bBasic = PB("basic"); /* Minimize clutter and distraction */
1632 const char *zType = PD("y",bBasic?"ci":"all"); /* Type of events. All if NULL */
1633 const char *zAfter = P("a"); /* Events after this time */
1634 const char *zBefore = P("b"); /* Events before this time */
1635 const char *zCirca = P("c"); /* Events near this time */
1636 const char *zMark = P("m"); /* Mark this event or an event this time */
1637 const char *zTagName = P("t"); /* Show events with this tag */
@@ -1732,11 +1743,11 @@
1732 /* For exact maching, inhibit links to the selected tag. */
1733 zThisTag = zTagName;
1734 }
1735
1736 /* Display a checkbox to enable/disable display of related check-ins. */
1737 if( !bBasic ) style_submenu_checkbox("rel", "Related", 0, 0);
1738
1739 /* Construct the tag match expression. */
1740 zTagSql = tagMatchExpression(matchStyle, zTagName, &zMatchDesc, &zError);
1741 }
1742
@@ -1864,13 +1875,11 @@
1864 blob_append(&sql, ")", -1);
1865 path_reset();
1866 addFileGlobExclusion(zChng, &sql);
1867 tmFlags |= TIMELINE_DISJOINT;
1868 db_multi_exec("%s", blob_sql_text(&sql));
1869 if( !bBasic ){
1870 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1871 }
1872 blob_appendf(&desc, "%d check-ins going from ",
1873 db_int(0, "SELECT count(*) FROM timeline"));
1874 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
1875 blob_append(&desc, " to ", -1);
1876 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1916,15 +1925,13 @@
1916 if( p_rid ){
1917 /* If both p= and d= are set, we don't have the uuid of d yet. */
1918 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
1919 }
1920 }
1921 if( !bBasic ){
1922 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1923 style_submenu_entry("n","Max:",4,0);
1924 timeline_y_submenu(1);
1925 }
1926 }else if( f_rid && g.perm.Read ){
1927 /* If f= is present, ignore all other parameters other than n= */
1928 char *zUuid;
1929 db_multi_exec(
1930 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1938,14 +1945,12 @@
1938 if( useDividers ) selectedRid = f_rid;
1939 blob_appendf(&desc, "Parents and children of check-in ");
1940 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1941 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
1942 tmFlags |= TIMELINE_DISJOINT;
1943 if( !bBasic ){
1944 style_submenu_checkbox("unhide", "Unhide", 0, 0);
1945 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1946 }
1947 }else{
1948 /* Otherwise, a timeline based on a span of time */
1949 int n;
1950 const char *zEType = "timeline item";
1951 char *zDate;
@@ -2225,34 +2230,29 @@
2225 /* timeline_submenu(&url, "Newer", "a", zDate, "b"); */
2226 zNewerButton = fossil_strdup(url_render(&url, "a", zDate, "b", 0));
2227 }
2228 free(zDate);
2229 }
2230 if( !bBasic ){
2231 if( zType[0]=='a' || zType[0]=='c' ){
2232 style_submenu_checkbox("unhide", "Unhide", 0, 0);
2233 }
2234 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
2235 style_submenu_entry("n","Max:",4,0);
2236 timeline_y_submenu(disableY);
2237 style_submenu_entry("t", "Tag Filter:", -8, 0);
2238 style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, 0);
2239 }
2240 }
2241 blob_zero(&cond);
2242 }
2243 if( bBasic ){
2244 timeline_submenu(&url, "Details", "basic", 0, 0);
2245 }else{
2246 timeline_submenu(&url, "Declutter", "basic", "1", 0);
2247 }
2248 if( PB("showsql") ){
2249 @ <pre>%h(blob_sql_text(&sql))</pre>
2250 }
2251 if( search_restrict(SRCH_CKIN)!=0 ){
2252 style_submenu_element("Search", "%R/search?y=c");
2253 }
 
 
2254 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
2255 if( useDividers && zMark && zMark[0] ){
2256 double r = symbolic_name_to_mtime(zMark);
2257 if( r>0.0 ) selectedRid = timeline_add_divider(r);
2258 }
@@ -2263,11 +2263,10 @@
2263
2264 /* Report any errors. */
2265 if( zError ){
2266 @ <p class="generalError">%h(zError)</p>
2267 }
2268 if( bBasic ) tmFlags |= TIMELINE_BASIC;
2269
2270 if( zNewerButton ){
2271 @ %z(xhref("class='button'","%z",zNewerButton))More&nbsp;&uarr;</a>
2272 }
2273 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, selectedRid, 0);
2274
--- src/timeline.c
+++ src/timeline.c
@@ -103,11 +103,10 @@
103 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
104 #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
105 #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
106 #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
107 #define TIMELINE_BISECT 0x0800 /* Show supplimental bisect information */
 
108 #endif
109
110 /*
111 ** Hash a string and use the hash to determine a background color.
112 */
@@ -265,19 +264,17 @@
264 }
265 zPrevDate[0] = 0;
266 mxWikiLen = db_get_int("timeline-max-comment", 0);
267 dateFormat = db_get_int("timeline-date-format", 0);
268 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
269 {
 
 
270 /* Undocumented query parameter commentformat=N takes a numeric parameter to
271 ** adjust the comment-format for testing purposes. */
272 const char *z = P("commentformat");
273 eCommentFormat = z ? atoi(z) : db_get_int("timeline-comment-format", 0);
274 }
275 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
276 bSeparateDetail = (eCommentFormat & 8)!=0; /* Bit 3 turns on the detail column */
277 switch( (eCommentFormat>>1)&3 ){
278 case 1: bHashAfterComment = 1; break;
279 case 2: bHashInDetail = 1; break;
280 default: bHashBeforeComment = 1; break;
@@ -565,10 +562,11 @@
562 @ style="background-color: %h(zBgClr);">
563 }else{
564 @ <td class="timelineTableCell timelineDetailCell">
565 }
566 }
567 cgi_printf("<span class='clutter'>");
568 if( zType[0]=='c' ){
569 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
570 }else{
571 cgi_printf("<span class='timelineDetail'>(");
572 }
@@ -638,11 +636,11 @@
636 cgi_printf(" id: %d&larr;%d", rid, srcId);
637 }else{
638 cgi_printf(" id: %d", rid);
639 }
640 }
641 cgi_printf(")</span></span>\n"); /* End of the details section */
642 }
643
644 tag_private_status(rid);
645
646 /* Generate extra hyperlinks at the end of the comment */
@@ -814,11 +812,11 @@
812 iRailPitch = atoi(PD("railpitch","0"));
813 showArrowheads = skin_detail_boolean("timeline-arrowheads");
814 circleNodes = skin_detail_boolean("timeline-circle-nodes");
815 colorGraph = skin_detail_boolean("timeline-color-graph-lines");
816
817 @ <script>
818 @ "use strict";
819 @ var css = "";
820 if( circleNodes ){
821 @ css += ".tl-node, .tl-node:after { border-radius: 50%%; }";
822 }
@@ -1141,10 +1139,25 @@
1139 }else{
1140 @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1";
1141 }
1142 }
1143 @ }
1144 @ }
1145 @ function changeDisplay(selector,value){
1146 @ var x = document.getElementsByClassName(selector);
1147 @ var n = x.length;
1148 @ for(var i=0; i<n; i++) {x[i].style.display = value;}
1149 @ }
1150 @ function declutter(){
1151 @ changeDisplay('clutter','none');
1152 @ changeDisplay('anticlutter','inline');
1153 @ checkHeight();
1154 @ }
1155 @ function reclutter(){
1156 @ changeDisplay('clutter','inline');
1157 @ changeDisplay('anticlutter','none');
1158 @ checkHeight();
1159 @ }
1160 @ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id);
1161 @ var lastY = 0;
1162 @ function checkHeight(){
1163 @ var h = absoluteY(lastRow);
@@ -1154,11 +1167,11 @@
1167 @ }
1168 @ setTimeout(checkHeight, 1000);
1169 @ }
1170 @ initGraph();
1171 @ checkHeight();
1172 @ </script>
1173 }
1174 }
1175
1176 /*
1177 ** Create a temporary table suitable for storing timeline data.
@@ -1324,11 +1337,11 @@
1337 az[i++] = "Wiki";
1338 }
1339 assert( i<=count(az) );
1340 }
1341 if( i>2 ){
1342 style_submenu_multichoice("y", i/2, az, isDisabled|STYLE_CLUTTER);
1343 }
1344 }
1345
1346 /*
1347 ** If the zChng string is not NULL, then it should be a comma-separated
@@ -1574,11 +1587,10 @@
1587 /*
1588 ** WEBPAGE: timeline
1589 **
1590 ** Query parameters:
1591 **
 
1592 ** a=TIMEORTAG After this event
1593 ** b=TIMEORTAG Before this event
1594 ** c=TIMEORTAG "Circa" this event
1595 ** m=TIMEORTAG Mark this event
1596 ** n=COUNT Suggested number of events in output
@@ -1626,12 +1638,11 @@
1638 int nEntry; /* Max number of entries on timeline */
1639 int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
1640 int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
1641 int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
1642 const char *zUser = P("u"); /* All entries by this user if not NULL */
1643 const char *zType = PD("y","all"); /* Type of events. All if NULL */
 
1644 const char *zAfter = P("a"); /* Events after this time */
1645 const char *zBefore = P("b"); /* Events before this time */
1646 const char *zCirca = P("c"); /* Events near this time */
1647 const char *zMark = P("m"); /* Mark this event or an event this time */
1648 const char *zTagName = P("t"); /* Show events with this tag */
@@ -1732,11 +1743,11 @@
1743 /* For exact maching, inhibit links to the selected tag. */
1744 zThisTag = zTagName;
1745 }
1746
1747 /* Display a checkbox to enable/disable display of related check-ins. */
1748 style_submenu_checkbox("rel", "Related", STYLE_CLUTTER, 0);
1749
1750 /* Construct the tag match expression. */
1751 zTagSql = tagMatchExpression(matchStyle, zTagName, &zMatchDesc, &zError);
1752 }
1753
@@ -1864,13 +1875,11 @@
1875 blob_append(&sql, ")", -1);
1876 path_reset();
1877 addFileGlobExclusion(zChng, &sql);
1878 tmFlags |= TIMELINE_DISJOINT;
1879 db_multi_exec("%s", blob_sql_text(&sql));
1880 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
 
 
1881 blob_appendf(&desc, "%d check-ins going from ",
1882 db_int(0, "SELECT count(*) FROM timeline"));
1883 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
1884 blob_append(&desc, " to ", -1);
1885 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1916,15 +1925,13 @@
1925 if( p_rid ){
1926 /* If both p= and d= are set, we don't have the uuid of d yet. */
1927 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
1928 }
1929 }
1930 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
1931 style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
1932 timeline_y_submenu(1);
 
 
1933 }else if( f_rid && g.perm.Read ){
1934 /* If f= is present, ignore all other parameters other than n= */
1935 char *zUuid;
1936 db_multi_exec(
1937 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1938,14 +1945,12 @@
1945 if( useDividers ) selectedRid = f_rid;
1946 blob_appendf(&desc, "Parents and children of check-in ");
1947 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1948 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
1949 tmFlags |= TIMELINE_DISJOINT;
1950 style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
1951 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
 
 
1952 }else{
1953 /* Otherwise, a timeline based on a span of time */
1954 int n;
1955 const char *zEType = "timeline item";
1956 char *zDate;
@@ -2225,34 +2230,29 @@
2230 /* timeline_submenu(&url, "Newer", "a", zDate, "b"); */
2231 zNewerButton = fossil_strdup(url_render(&url, "a", zDate, "b", 0));
2232 }
2233 free(zDate);
2234 }
2235 if( zType[0]=='a' || zType[0]=='c' ){
2236 style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
2237 }
2238 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
2239 style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
2240 timeline_y_submenu(disableY);
2241 style_submenu_entry("t", "Tag Filter:", -8, STYLE_CLUTTER);
2242 style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, STYLE_CLUTTER);
2243 }
2244 blob_zero(&cond);
 
 
 
 
 
 
 
2245 }
2246 if( PB("showsql") ){
2247 @ <pre>%h(blob_sql_text(&sql))</pre>
2248 }
2249 if( search_restrict(SRCH_CKIN)!=0 ){
2250 style_submenu_element("Search", "%R/search?y=c");
2251 }
2252 style_submenu_jsbutton("Advanced", STYLE_BASIC, "reclutter()");
2253 style_submenu_jsbutton("Basic", STYLE_CLUTTER, "declutter()");
2254 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
2255 if( useDividers && zMark && zMark[0] ){
2256 double r = symbolic_name_to_mtime(zMark);
2257 if( r>0.0 ) selectedRid = timeline_add_divider(r);
2258 }
@@ -2263,11 +2263,10 @@
2263
2264 /* Report any errors. */
2265 if( zError ){
2266 @ <p class="generalError">%h(zError)</p>
2267 }
 
2268
2269 if( zNewerButton ){
2270 @ %z(xhref("class='button'","%z",zNewerButton))More&nbsp;&uarr;</a>
2271 }
2272 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, selectedRid, 0);
2273

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button