#include "pch.h"
class NavPaneImpl : public NavPane {
private:
class Topic : public Pane {
public:
TRef<Topic> m_ptopicParent;
TRef<Pane> m_ppane;
TRef<ModifiableString> m_pstring;
TRef<ModifiableColorValue> m_pcolor;
ZString m_str;
ZString m_strMain;
ZString m_strSecondary;
ZString m_strStartSub;
int m_indent;
Color m_color;
Color m_colorHighlight;
bool m_bInside;
TRef<StringEventSourceImpl> m_peventSource;
Topic(
StringEventSourceImpl* peventSource,
Topic* ptopicParent,
IEngineFont* pfont,
int indent,
int width,
const ZString& str,
const ZString& strMain,
const ZString& strSecondary,
const Color& colorHighlight
) :
m_peventSource(peventSource),
m_ptopicParent(ptopicParent),
m_str(str),
m_strMain(strMain),
m_strSecondary(strSecondary),
m_indent(indent * 8),
m_colorHighlight(colorHighlight),
m_bInside(false),
m_strStartSub(ZString("hlpStartSub"))
{
m_ppane =
new AnimatedImagePane(
CreateStringImage(
JustifyLeft(),
pfont,
m_pcolor = new ModifiableColorValue(Color::White()),
width - m_indent,
m_pstring = new ModifiableString(str),
4
)
);
InternalSetOffset(m_ppane, WinPoint(m_indent, 0));
InsertAtBottom(m_ppane);
}
void SetColor(const Color& color)
{
m_color = color;
if (!m_bInside) {
m_pcolor->SetValue(color);
}
}
Pane* GetPane()
{
return this;
}
void UpdateLayout()
{
Child()->UpdateLayout();
InternalSetSize(WinPoint(
Child()->XSize() + m_indent,
Child()->YSize()
));
}
void MouseEnter(IInputProvider* pprovider, const Point& point)
{
m_bInside = true;
m_pcolor->SetValue(m_colorHighlight);
}
void MouseLeave(IInputProvider* pprovider)
{
m_bInside = false;
m_pcolor->SetValue(m_color);
}
MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
{
if (button == 0 && bDown) {
m_peventSource->Trigger(m_strMain);
}
return MouseResult();
}
};
typedef TList<TRef<Topic> > TopicList;
TopicList m_listTopic;
TRef<StringEventSourceImpl> m_peventSource;
TRef<IEngineFont> m_pfont;
TRef<ColumnPane> m_pcolumn;
TRef<Topic> m_ptopicSelected;
Color m_color;
Color m_colorSelected;
Color m_colorHighlight;
public:
NavPaneImpl(
IObjectList* plist,
const Point& size,
const Color& color,
const Color& colorSelected,
const Color& colorHighlight,
IEngineFont* pfont
) :
m_color(color),
m_colorSelected(colorSelected),
m_colorHighlight(colorHighlight),
m_pfont(pfont)
{
m_peventSource = new StringEventSourceImpl();
InternalSetSize(WinPoint::Cast(size));
m_pcolumn = new ColumnPane();
InsertAtBottom(m_pcolumn);
ReadTopicList(plist, 0, NULL);
m_ptopicSelected = m_listTopic.GetFront();
UpdatePanes();
}
void ReadTopicList(IObjectList* plist, int indent, Topic* ptopicParent)
{
plist->GetFirst();
while (plist->GetCurrent() != NULL) {
TRef<IObjectPair> ppair; CastTo(ppair, plist->GetCurrent());
TRef<StringValue> pstring; CastTo(pstring, ppair->GetNth(0));
TRef<StringValue> pstringMain; CastTo(pstringMain, ppair->GetNth(1));
TRef<StringValue> pstringSecondary; CastTo(pstringSecondary, ppair->GetNth(2));
TRef<IObjectList> plistSubTopic; CastTo(plistSubTopic, ppair->GetLastNth(3));
TRef<Topic> ptopic =
new Topic(
m_peventSource,
ptopicParent,
m_pfont,
indent,
XSize(),
pstring->GetValue(),
pstringMain->GetValue(),
pstringSecondary->GetValue(),
m_colorHighlight
);
m_listTopic.PushEnd(ptopic);
if (plistSubTopic->GetCount() != 0) {
ReadTopicList(plistSubTopic, indent + 1, ptopic);
}
plist->GetNext();
}
}
bool IsTopicSelected(Topic* ptopicParent)
{
TRef<Topic> ptopic = m_ptopicSelected;
while (ptopic != NULL) {
if (ptopic == ptopicParent) {
return true;
}
ptopic = ptopic->m_ptopicParent;
}
return false;
}
bool IsTopicOpen(Topic* ptopic)
{
Topic* ptopicParent = ptopic->m_ptopicParent;
if (ptopicParent == NULL) {
return true;
}
while (ptopicParent != NULL) {
if (!IsTopicSelected(ptopicParent)) {
return false;
}
ptopicParent = ptopicParent->m_ptopicParent;
}
return true;
}
void UpdatePanes()
{
m_pcolumn->RemoveAllChildren();
TopicList::Iterator iter(m_listTopic);
while (!iter.End()) {
Topic* ptopic = iter.Value();
if (IsTopicOpen(ptopic)) {
ptopic->SetColor(
IsTopicSelected(ptopic)
? m_colorSelected
: m_color
);
m_pcolumn->InsertAtBottom(ptopic->GetPane());
}
iter.Next();
}
}
Topic* FindTopic(const ZString& str)
{
TopicList::Iterator iter(m_listTopic);
while (!iter.End()) {
Topic* ptopic = iter.Value();
if (ptopic->m_strMain == str) {
return ptopic;
}
iter.Next();
}
return NULL;
}
void SetTopic(const ZString& str)
{
m_ptopicSelected = FindTopic(str);
UpdatePanes();
}
const ZString& GetSecondary(const ZString& str)
{
Topic* ptopic = FindTopic(str);
if (ptopic) {
return ptopic->m_strSecondary;
} else if (str=="hlpStart") {
ptopic = FindTopic("hlpa0");
if (ptopic) {
return ptopic->m_strStartSub;
} else {
return str;
}
}
else {
return str;
}
}
virtual TRef<IStringEventSource> GetEventSource()
{
return m_peventSource;
}
void UpdateLayout()
{
m_pcolumn->UpdateLayout();
}
};
class NavPaneFactory : public IFunction {
public:
TRef<IObject> Apply(ObjectStack& stack)
{
TRef<IObjectList> plist; CastTo(plist, (IObject*)stack.Pop());
TRef<PointValue> psize; CastTo(psize, (IObject*)stack.Pop());
TRef<ColorValue> pcolor; CastTo(pcolor, (IObject*)stack.Pop());
TRef<ColorValue> pcolorSelected; CastTo(pcolorSelected, (IObject*)stack.Pop());
TRef<ColorValue> pcolorHighlight; CastTo(pcolorHighlight, (IObject*)stack.Pop());
TRef<FontValue> pfont; CastTo(pfont, (IObject*)stack.Pop());
return
new NavPaneImpl(
plist,
psize->GetValue(),
pcolor->GetValue(),
pcolorSelected->GetValue(),
pcolorHighlight->GetValue(),
pfont->GetValue()
);
}
};
void AddNavPaneFactory(
INameSpace* pns
) {
pns->AddMember("NavPane", new NavPaneFactory());
}