Source file: /~heha/enas/Convac-Ätzer/Firmware-190517.zip/ListView.cpp

#include "Convac.h"	// ListView class
#include <string.h>	// memcpy

extern DISP d;

void ListView::onLenChange() {
 byte H=B-T;		// Höhe-1 des Fensters
 if (pos+H>=len) {	// Freiraum hinten? (<pos> verkleinern?)
  if (H>=len) {		// Weißraum verbleibt weil Liste zu kurz?
   H=len-1;
   pos=0;
   d.flags=d.R2_ZERO;	// Pixel löschen
   d.fillRect(L,T+len,R-SBW,B);	// Ungenutzten Bereich für immer weiß
  }
  else pos=len-H-1;	// Kein Weißraum wenn Liste voll
 }
 paintScrollbar();
 if (!len) return;	// Nichts ausmalen
 d.andClip(L,T,R-SBW,T+H);	// Rest zum Ausmalen „markieren“
 setRedraw();
}

// Symbolischen Rollbalken malen, SBW (10) Pixel breit
// (kann eh' nur mit Tasten „bedient“ werden)
void ListView::paintScrollbar() {
 d.flags=d.R2_ZERO;	// Pixel löschen
 d.fillRect(R-SBW+1,T,R,B);
 d.flags=d.COLOR|d.R2_COPYPEN;	// Pixel setzen
 d.drawRect(R-SBW+2,T,R,B);
 byte t=T+2;
 if (pos) {
  d.drawPixel(R-SBM,t); t++; // Pfeil oben
  d.drawLine(R-SBM-1,t,R-SBM+1,t); t++;
  d.drawLine(R-SBM-2,t,R-SBM+2,t); t+=2;
 }
 word H=B-T+1;		// Höhe des Fensters (Pixel)
 byte b=B-2;
 if (pos+H<len) {
  d.drawPixel(R-SBM,b); b--; // Pfeil unten
  d.drawLine(R-SBM-1,b,R-SBM+1,b); b--;
  d.drawLine(R-SBM-2,b,R-SBM+2,b); b-=2;
 }
 if (len<=H) return;	// Liste kürzer: Kein Thumb (Kein Scrollbar?)
 byte hs=b-t+1;		// Höhe Thumb-Bereich (Pixel)
 byte tl=(byte)H*hs/len;	// Länge des Thumbs (Pixel)
 if (tl<3) tl=3;	// Minimum zur Erkennbarkeit
 byte ty=word(pos*(hs-tl))/word(len-H);	// obere Thumb-Position
 ty+=t;
 d.fillRect(R-6,ty,R-2,ty+tl-1);
}

int ListView::posIntoView(word ip, byte ih) {
 if (!ih) ip*=ih=dih;
 byte h=B-T;		// Höhe Fenster minus 1
 --ih;
 if (ip<pos || ih>h) return ip-pos;	// herunterscrollen, hoch in Liste, dy<0
 if (ip+ih>pos+h) return ip+ih-pos-h;	// hochscrollen, hinunter in Liste, dy>0
 return 0;		// keine Aktion
}

void ListView::scrollIntoView(word ip, byte ih) {
 int dy=posIntoView(ip,ih);
 if (!dy) return;	// keine Aktion
 pos+=dy;		// Ändern der ersten sichtbaren Pixelzeile
 paintScrollbar();
 byte ct=T, cb=B;	// Clip-Top und Clip-Bottom
 byte h=B-T;		// Höhe Fenster minus 1
 if (-h<=dy && dy<=h) {
  d.L=L; d.T=T; d.R=R-SBW; d.B=B;
  d.scroll(0,dy);
  if (dy<0) cb=ct-dy-1; else ct=cb-dy+1;
 }
 d.andClip(L,ct,R-SBW,cb);
 setRedraw();		// Scrollen: Teilweise oder alles neuzeichnen
}

void ListView::collapse(word ip, int dy) {
 word h=len;		// Größere der beiden Längen fangen
 byte H=B-T;		// Höhe der Listbox-1
 len-=dy;		// Neue Gesamtlänge
 if (dy<0) h=len;
 else if (pos && pos+H>=len) {	// Freiraum hinten? (<pos> ist zu verkleinern?)
  onLenChange();
  return;		// erst mal zu kompliziert zum Scrollen: Neuaufbau
 }
 h-=pos;		// Anzahl Pixel-1 hinter <pos>
 assert((int)len>=0,__LINE__);
 paintScrollbar();
 assert(len>=ip,__LINE__);
 ip-=pos;		// Stelle auf Bildschirm
 if ((int)ip<0) ip=0;	// Wenn oberhalb, tue so als wär's die obere Listen-Rand (kommt nie vor)
 h-=ip;			// Anzahl Pixel-1 hinter {Einfügestelle ODER oberer Listen-Rand}
 assert(h>=0,__LINE__);
 if (ip>H) return;	// Wenn unterhalb, tue nichts
// Ab hier ist <ip> ein Byte
 H-=ip;			// Anzahl Pixel-1 hinter Einfügestelle
 if (h>H) h=H;		// Anzahl _sichtbarer_ Pixel-1 hinter {}
// Ab hier ist auch <h> ein Byte
 d.L=L; d.R=R-SBW; d.B=(d.T=T+ip)+h;	// Operations-Rechteck
 if (dy<0) {		// Einfüge-Operation
  if (int(dy+h)>=0) {
   d.scroll(0,dy);
   d.B=d.T-dy-1;
  }
 }else{			// Lösch-Operation
  if (h>=(word)dy) {
   d.scroll(0,dy);
   d.T=d.B-dy+1;
  }
 }
 d.andClip(d.L,d.T,d.R,d.B);
 setRedraw();
}

bool ListView::itemVisible(word ip, byte ih) {
 if (!ih) ip*=ih=dih;
 return ip+ih>pos && ip<=pos+(B-T);
}

bool ListView::itemInvalid(word ip, byte ih) {
 if (!ih) ip*=ih=dih;
 ip+=T;
 return ip+ih>pos+d.clip.T && ip<=pos+d.clip.B;
}

void ListView::andItemClip(word ip, byte ih) {
 if (!ih) ip*=ih=dih;
 char dy=ip-pos;	// muss in ein (vzb.) Byte passen da sichtbar
 byte t=T; if (ip>pos) t+=dy;
 byte b=B; if (ip+ih<=pos+b-T) b=T+dy+ih-1;
 d.andClip(L,t,R-SBW,b);
}

void ListView::setFullClip() {
 memcpy(&d.clip.L,&L,4);
}

void ListView::fillItem(int ip, int ih, byte l, byte r) {
 if (!ih) ip*=ih=dih;
 l+=L;
 byte rr=r;	// retten zur Überlauffeststellung (Carry)
 byte rmax=R-SBW;
 r+=L; if (r<rr || r>rmax) r=rmax;	// begrenzen
 if ((ip-=pos)<0) {		// Anfang oberhalb?
  if ((ih+=ip)<0) return;	// verringern! Itemende außerhalb oben
  ip=0;
 }
 byte h=B-T;
 if (ip>h) return;		// außerhalb unten
 if (h>=ih) h=ih-1;
 d.fillRect(l,T+ip,r,T+ip+h);
}

void ListView::xorFocusRect(word ip, byte ih, byte l, byte r) {
 if (!ih) ip*=ih=dih;
 l+=L;
 byte rr=r;
 byte rmax=R-SBW;
 r+=L; if (r<rr || r>rmax) r=rmax;
 byte t=ip-pos;	// sollte nie <0 werden!
 t+=T;
 ::xorFocusRect(l,t,r,t+ih-1);
}
Detected encoding: UTF-80