ultimatepp/uppsrc/CtrlLib/DropList.cpp
2026-05-03 15:40:29 +02:00

343 lines
No EOL
5.9 KiB
C++

#include "CtrlLib.h"
namespace Upp {
DropList::DropList()
{
displayall = false;
valueconvert = &NoConvert();
valuedisplay = NULL;
dropfocus = false;
notnull = false;
alwaysdrop = false;
SetupDropPush();
NoInitFocus();
EnableDrop(false);
list.WhenSelect = THISBACK(Select);
list.WhenCancel = THISBACK(Cancel);
dropwidth = 0;
usewheel = true;
}
int DropList::FindKey(const Value& k) const
{
return key.Find(k);
}
void DropList::Sync() {
Value v;
if(displayall)
v = value;
int i = key.Find(value);
const Display& d = valuedisplay ? *valuedisplay : i >= 0 ? list.GetDisplay(i)
: list.GetDisplay();
if(i >= 0) v = list.Get(i);
MultiButton::SetDisplay(d);
MultiButton::SetValueCy(list.GetLineCy());
v = valueconvert->Format(v);
Set(v, false);
}
void DropList::Change(int q) {
if(key.GetCount() == 0) return;
int i = key.Find(value);
for(int l = 0; l < list.GetCount(); l++) {
i += q;
if(i >= key.GetCount()) i = key.GetCount() - 1;
if(i < 0) i = 0;
if(list.IsLineEnabled(i) && list.GetLineCy(i) > 0) {
if(value != key[i]) {
value = key[i];
Sync();
UpdateAction();
}
return;
}
}
}
bool DropList::Key(dword k, int) {
if(IsReadOnly()) return false;
switch(k) {
case K_ALT_DOWN:
Drop();
break;
case K_DOWN:
case K_RIGHT:
Change(1);
break;
case K_UP:
case K_LEFT:
Change(-1);
break;
default:
if(k >= 32 && k < K_CHAR_LIM) {
bool b = list.Key(k);
if(list.GetCursor() >= 0 && list.GetCursor() < key.GetCount() && key[list.GetCursor()] != value)
Select();
return b;
}
return false;
}
return true;
}
void DropList::MouseWheel(Point, int zdelta, dword)
{
if(usewheel)
Change(zdelta < 0 ? 1 : -1);
}
void DropList::Drop() {
if(IsReadOnly()) return;
if(dropfocus)
SetFocus();
WhenDrop();
list.SetCursor(key.Find(value));
list.PopUp(this, dropwidth);
}
void DropList::DropPush()
{
Drop();
}
void DropList::Select() {
int c = list.GetCursor();
if(c >= 0)
value = key[c];
if(dropfocus)
SetFocus();
Sync();
UpdateAction();
}
void DropList::Cancel() {
if(dropfocus)
SetFocus();
Sync();
}
void DropList::Remove(int i)
{
key.Remove(i);
list.Remove(i);
Adjust();
}
void DropList::ClearList() {
key.Clear();
list.Clear();
Sync();
EnableDrop(false);
}
void DropList::Clear() {
ClearList();
value = Value();
Sync();
Update();
}
DropList& DropList::Add(const Value& _key, const Value& text, bool enable)
{
key.Add(_key);
list.Add(text);
if(!enable)
list.SetLineCy(list.GetCount() - 1, 0);
EnableDrop();
Sync();
return *this;
}
DropList& DropList::Add(std::initializer_list<std::pair<Value, Value>> init)
{
for(const auto& i : init)
Add(i.first, i.second);
return *this;
}
struct DummyValue__ {};
DropList& DropList::AddSeparator()
{
key.Add(RawToValue(DummyValue__()));
list.AddSeparator();
EnableDrop();
Sync();
return *this;
}
void DropList::Trim(int n) {
if(GetIndex() >= n)
SetIndex(0);
key.Trim(n);
list.SetCount(n);
Sync();
EnableDrop(n);
}
void DropList::SetData(const Value& data) {
if(value != data) {
value = data;
Update();
Sync();
}
}
Value DropList::GetData() const {
return notnull && IsNull(value) ? NotNullError() : value;
}
Value DropList::GetValue() const {
int i = FindKey(value);
return i < 0 ? Null : GetValue(i);
}
void DropList::SetValue(int i, const Value& v) {
list.Set(i, v);
EnableDrop();
Sync();
}
void DropList::SetValue(const Value& v) {
int i = FindKey(value);
if(i >= 0)
SetValue(i, v);
Sync();
}
DropList& DropList::SetValueConvert(const Convert& cv)
{
valueconvert = &cv;
Sync();
return *this;
}
DropList& DropList::SetConvert(const Convert& cv)
{
list.SetConvert(cv);
return SetValueConvert(cv);
}
DropList& DropList::SetDisplay(int i, const Display& d)
{
list.SetDisplay(i, d);
Sync();
return *this;
}
DropList& DropList::SetDisplay(const Display& d)
{
list.SetDisplay(d);
Sync();
return *this;
}
DropList& DropList::SetDisplay(const Display& d, int lcy)
{
SetDisplay(d);
SetLineCy(lcy);
Sync();
return *this;
}
DropList& DropList::ValueDisplay(const Display& d)
{
valuedisplay = &d;
Sync();
return *this;
}
void DropList::Adjust()
{
int i = FindKey(value);
if(i < 0) {
if(GetCount())
SetIndex(0);
else
SetData(Null);
}
}
void DropList::Adjust(const Value& k)
{
int i = FindKey(value);
if(i < 0 && GetCount())
SetData(k);
}
Value DropList::Format(const Value& q) const {
int i = FindKey(q);
return valueconvert->Format(i < 0 ? displayall ? q : Value() : GetValue(i));
}
DropList& DropList::AlwaysDrop(bool e)
{
alwaysdrop = e;
if(e)
EnableDrop();
return *this;
}
void Append(DropList& list, const VectorMap<Value, Value>& values)
{
for(int i = 0; i < values.GetCount(); i++)
list.Add(values.GetKey(i), values[i]);
}
void Append(MapConvert& convert, const VectorMap<Value, Value>& values)
{
for(int i = 0; i < values.GetCount(); i++)
convert.Add(values.GetKey(i), values[i]);
}
void Append(DropList& list, const VectorMap<int, String>& values)
{
for(int i = 0; i < values.GetCount(); i++)
list.Add(values.GetKey(i), values[i]);
}
void Append(MapConvert& convert, const VectorMap<int, String>& values)
{
for(int i = 0; i < values.GetCount(); i++)
convert.Add(values.GetKey(i), values[i]);
}
void Append(DropList& list, const MapConvert& convert)
{
for(int i = 0; i < convert.GetCount(); i++)
list.Add(convert.GetKey(i), convert.GetValue(i));
}
void operator*=(DropList& list, const VectorMap<Value, Value>& values)
{
list.ClearList();
Append(list, values);
}
void operator*=(MapConvert& convert, const VectorMap<Value, Value>& values)
{
convert.Clear();
Append(convert, values);
}
void operator*=(DropList& list, const VectorMap<int, String>& values)
{
list.ClearList();
Append(list, values);
}
void operator*=(MapConvert& convert, const VectorMap<int, String>& values)
{
convert.Clear();
Append(convert, values);
}
void operator*=(DropList& list, const MapConvert& convert)
{
list.ClearList();
Append(list, convert);
}
}