This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/utils/vgui/lib/EditPanel.cpp

603 lines
9.9 KiB
C++

//========= Copyright ?1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include<stdio.h>
#include<stdarg.h>
#include<VGUI_EditPanel.h>
#include<VGUI_InputSignal.h>
#include<VGUI_App.h>
#include<VGUI_Font.h>
using namespace vgui;
namespace
{
class FooDefaultEditPanelSignal : public InputSignal
{
public:
FooDefaultEditPanelSignal(EditPanel* editPanel)
{
_editPanel=editPanel;
}
public:
virtual void cursorMoved(int x,int y,Panel* panel)
{
}
virtual void cursorEntered(Panel* panel)
{
}
virtual void cursorExited(Panel* panel)
{
}
virtual void mousePressed(MouseCode code,Panel* panel)
{
_editPanel->requestFocus();
_editPanel->repaint();
}
virtual void mouseDoublePressed(MouseCode code,Panel* panel)
{
}
virtual void mouseReleased(MouseCode code,Panel* panel)
{
}
virtual void mouseWheeled(int delta,Panel* panel)
{
}
virtual void keyPressed(KeyCode code,Panel* panel)
{
}
virtual void keyTyped(KeyCode code,Panel* panel)
{
bool shift=(_editPanel->isKeyDown(KEY_LSHIFT)||_editPanel->isKeyDown(KEY_RSHIFT));
switch(code)
{
case KEY_UP:
{
_editPanel->doCursorUp();
break;
}
case KEY_DOWN:
{
_editPanel->doCursorDown();
break;
}
case KEY_LEFT:
{
_editPanel->doCursorLeft();
break;
}
case KEY_RIGHT:
{
_editPanel->doCursorRight();
break;
}
case KEY_HOME:
{
_editPanel->doCursorToStartOfLine();
break;
}
case KEY_END:
{
_editPanel->doCursorToEndOfLine();
break;
}
case KEY_BACKSPACE:
{
_editPanel->doCursorBackspace();
break;
}
case KEY_DELETE:
{
_editPanel->doCursorDelete();
break;
}
case KEY_ENTER:
{
_editPanel->doCursorNewLine();
break;
}
default:
{
_editPanel->doCursorInsertChar(_editPanel->getApp()->getKeyCodeChar(code,shift));
break;
}
case KEY_LSHIFT:
case KEY_RSHIFT:
case KEY_LALT:
case KEY_RALT:
case KEY_LCONTROL:
case KEY_RCONTROL:
{
break;
}
}
}
virtual void keyReleased(KeyCode code,Panel* panel)
{
}
virtual void keyFocusTicked(Panel* panel)
{
bool blink;
int nextBlinkTime;
_editPanel->getCursorBlink(blink,nextBlinkTime);
int time=_editPanel->getApp()->getTimeMillis();
if(time>nextBlinkTime)
{
_editPanel->setCursorBlink(!blink);
}
}
private:
EditPanel* _editPanel;
};
}
EditPanel::EditPanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
{
_cursor[0]=0;
_cursor[1]=0;
_font=null;
setCursorBlink(true);
addInputSignal(new FooDefaultEditPanelSignal(this));
getLine(0);
}
void EditPanel::paintBackground()
{
int wide,tall;
getPaintSize(wide,tall);
drawSetColor(Scheme::sc_white);
drawFilledRect(0,0,wide,tall);
}
void EditPanel::addLine()
{
}
Dar<char>* EditPanel::getLine(int lineIndex)
{
if(lineIndex<0)
{
return null;
}
if((lineIndex==0)&&(_lineDarDar.getCount()==0))
{
Dar<char>* lineDar=new Dar<char>;
_lineDarDar.addElement(lineDar);
return lineDar;
}
if(lineIndex>=_lineDarDar.getCount())
{
return null;
}
return _lineDarDar[lineIndex];
}
void EditPanel::getText(int lineIndex, int offset,char* buf,int bufLen)
{
if((lineIndex>=0)&&(lineIndex<_lineDarDar.getCount()))
{
Dar<char>* dataStr=_lineDarDar[lineIndex];
int j=0;
for(int i=offset;i<dataStr->getCount()&&(j<bufLen-1);i++,j++)
{
buf[i-offset]=(*dataStr)[i];
}
buf[j]=0;
}
}
void EditPanel::setChar(Dar<char>* lineDar,int x,char ch,char fill)
{
if((lineDar==null)||(x<0))
{
return;
}
int count=lineDar->getCount();
if(x>=count)
{
lineDar->ensureCapacity(x+1);
lineDar->setCount(x+1);
for(int i=count;i<x;i++)
{
lineDar->setElementAt(fill,i);
}
}
lineDar->setElementAt(ch,x);
}
void EditPanel::setChar(Dar<char>* lineDar,int x,char ch)
{
setChar(lineDar,x,ch,' ');
}
int EditPanel::getLineCount()
{
return _lineDarDar.getCount();
}
int EditPanel::getVisibleLineCount()
{
int wide,tall;
getPaintSize(wide,tall);
Font* font=_font;
if(font==null)
{
font=getApp()->getScheme()->getFont(Scheme::sf_primary1);
}
return tall/font->getTall();
}
void EditPanel::setCursorBlink(bool state)
{
_cursorBlink=state;
_cursorNextBlinkTime=getApp()->getTimeMillis()+400;
repaint();
}
void EditPanel::getCursorBlink(bool& blink,int& nextBlinkTime)
{
blink=_cursorBlink;
nextBlinkTime=_cursorNextBlinkTime;
}
void EditPanel::shiftLineLeft(Dar<char>* lineDar,int x,int count)
{
if((x<0)||(x>lineDar->getCount()))
{
return;
}
if(count<0)
{
return;
}
for(int i=x;i<lineDar->getCount();i++)
{
int xx=x-count;
if(xx>=0)
{
setChar(lineDar,xx,(*lineDar)[i]);
}
}
lineDar->setCount(lineDar->getCount()-count);
}
void EditPanel::shiftLineRight(Dar<char>* lineDar,int x,int count)
{
if(x<0)
{
return;
}
if(count<0)
{
return;
}
for(int i=lineDar->getCount()-1;i>=x;i--)
{
setChar(lineDar,i-count,(*lineDar)[i]);
}
}
int EditPanel::spatialCharOffsetBetweenTwoLines(Dar<char>* srcDar,Dar<char>* dstDar,int x)
{
if((srcDar==null)||(dstDar==null))
{
return x;
}
Font* font=_font;
if(font==null)
{
font=getApp()->getScheme()->getFont(Scheme::sf_primary1);
}
int i;
int x0=0;
for(i=0;i<x;i++)
{
char ch=' ';
if(i<srcDar->getCount())
{
ch=(*srcDar)[i];
}
int a,b,c;
font->getCharABCwide(ch,a,b,c);
x0+=a+b+c;
}
int x1=0;
for(i=0;;i++)
{
char ch=' ';
if(i<dstDar->getCount())
{
ch=(*dstDar)[i];
}
int a,b,c;
font->getCharABCwide(ch,a,b,c);
int mid=x1+(a+b+c)/2;
if (x1>x0)
{
if(mid>x0)
{
}
else if (x1+(a+b+c)>x0)
{
return i+1;
}
}
else
{
if(mid>x0)
{
return i;
}
else if(x1+(a+b+c)>x0)
{
return i+1;
}
}
x1+=a+b+c;
}
}
void EditPanel::paint()
{
Font* font=_font;
if(font==null)
{
font=getApp()->getScheme()->getFont(Scheme::sf_primary1);
}
drawSetTextFont(font);
drawSetTextColor(Scheme::sc_black);
int yy=0;
for(int j=0;j<_lineDarDar.getCount();j++)
{
int cx=0;
int xx=0;
Dar<char>* lineDar=_lineDarDar[j];
for(int i=0;i<lineDar->getCount();i++)
{
char ch=(*lineDar)[i];
drawPrintChar(xx,yy,ch);
if((_cursor[0]==i)&&(_cursor[1]==j))
{
cx=xx;
}
int a,b,c;
font->getCharABCwide(ch,a,b,c);
xx+=a+b+c;
}
if((_cursor[1]==j)&&_cursorBlink)
{
if(_cursor[0]>=lineDar->getCount())
{
int a,b,c;
font->getCharABCwide(' ',a,b,c);
cx=xx+(_cursor[0]-lineDar->getCount())*(a+b+c);
}
drawSetColor(255,0,0,0);
drawFilledRect(cx-1,yy,cx+1,yy+font->getTall());
}
yy+=font->getTall();
}
}
void EditPanel::doCursorUp()
{
_cursor[0]=spatialCharOffsetBetweenTwoLines(getLine(_cursor[1]),getLine(_cursor[1]-1),_cursor[0]);
_cursor[1]--;
if(_cursor[1]<0)
{
_cursor[1]=0;
}
setCursorBlink(true);
repaint();
}
void EditPanel::doCursorDown()
{
int lCount=getVisibleLineCount();
_cursor[0]=spatialCharOffsetBetweenTwoLines(getLine(_cursor[1]),getLine(_cursor[1]+1),_cursor[0]);
if(lCount>getLineCount())
{
lCount=getLineCount();
}
if(_cursor[1]+1>=lCount)
{
return;
}
_cursor[1]++;
setCursorBlink(true);
repaint();
}
void EditPanel::doCursorLeft()
{
_cursor[0]--;
if(_cursor[0]<0)
{
_cursor[0]=0;
}
setCursorBlink(true);
repaint();
}
void EditPanel::doCursorRight()
{
_cursor[0]++;
setCursorBlink(true);
repaint();
}
void EditPanel::doCursorToStartOfLine()
{
_cursor[0]=0;
setCursorBlink(true);
repaint();
}
void EditPanel::doCursorToEndOfLine()
{
Dar<char>* lineDar=getLine(_cursor[1]);
if(lineDar==null)
{
return;
}
_cursor[0]=lineDar->getCount();
setCursorBlink(true);
repaint();
}
void EditPanel::doCursorInsertChar(char ch)
{
Dar<char>* lineDar=getLine(_cursor[1]);
if(lineDar==null)
{
return;
}
shiftLineRight(lineDar,_cursor[0],1);
setChar(lineDar,_cursor[0],ch);
doCursorRight();
repaint();
}
void EditPanel::doCursorBackspace()
{
Dar<char>* lineDar=getLine(_cursor[1]);
if(lineDar==null)
{
return;
}
if(_cursor[0]==0)
{
Dar<char>* prevLineDar=getLine(_cursor[1]-1);
if(prevLineDar==null)
{
return;
}
int len=prevLineDar->getCount();
for(int i=0;i<lineDar->getCount();i++)
{
setChar(prevLineDar,len+i,(*lineDar)[i]);
}
if(_cursor[1]>=0)
{
_lineDarDar.removeElementAt(_cursor[1]);
doCursorUp();
_cursor[0]=prevLineDar->getCount();
}
repaint();
}
else
{
shiftLineLeft(lineDar,_cursor[0],1);
doCursorLeft();
repaint();
}
}
void EditPanel::doCursorNewLine()
{
Dar<char>* lineDar=getLine(_cursor[1]);
if(lineDar==null)
{
return;
}
Dar<char>* newLineDar=new Dar<char>;
_lineDarDar.insertElementAt(newLineDar,_cursor[1]+1);
for(int i=_cursor[0];i<lineDar->getCount();i++)
{
setChar(newLineDar,i-_cursor[0],(*lineDar)[i]);
}
lineDar->setCount(_cursor[0]);
_cursor[0]=0;
doCursorDown();
repaint();
}
void EditPanel::doCursorDelete()
{
Dar<char>* lineDar=getLine(_cursor[1]);
if(lineDar==null)
{
return;
}
doCursorRight();
shiftLineRight(lineDar,_cursor[0],1);
doCursorLeft();
repaint();
}
void EditPanel::doCursorPrintf(char* format,...)
{
va_list argList;
va_start(argList,format);
char buf[8192];
vsprintf(buf,format,argList);
va_end(argList);
for(int i=0;i<sizeof(buf);i++)
{
if(buf[i]==0)
{
break;
}
if(buf[i]=='\n')
{
doCursorNewLine();
continue;
}
doCursorInsertChar(buf[i]);
}
repaint();
}
void EditPanel::setFont(Font* font)
{
_font=font;
repaint();
}