comments and revisions
This commit is contained in:
parent
54a765d809
commit
3849f459c4
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of GContainer.
|
\brief Implementation of GContainer.
|
||||||
|
|
||||||
Implementation of GContainer, a barebones widget that can contain child widgets.
|
Implementation of GContainer, a barebones widget that can contain child widgets.
|
||||||
<br>$Id: GewiContainer.cpp,v 1.5 2003/06/09 03:28:43 cozman Exp $<br>
|
<br>$Id: GewiContainer.cpp,v 1.6 2003/06/12 09:32:32 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -22,6 +22,8 @@
|
|||||||
namespace Gewi
|
namespace Gewi
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//all the work for GContainer is now done by WidgetList//
|
||||||
|
|
||||||
void GContainer::AddChild(GWidget *widget)
|
void GContainer::AddChild(GWidget *widget)
|
||||||
{
|
{
|
||||||
WidgetNode *node = new WidgetNode;
|
WidgetNode *node = new WidgetNode;
|
||||||
@ -56,7 +58,7 @@ void GContainer::Move(float x, float y)
|
|||||||
|
|
||||||
void GContainer::Message(SDL_Event *rawEvent, GewiEvent event, Uint16 mouseX, Uint16 mouseY, char ch)
|
void GContainer::Message(SDL_Event *rawEvent, GewiEvent event, Uint16 mouseX, Uint16 mouseY, char ch)
|
||||||
{
|
{
|
||||||
rChildList.Message(rawEvent,event,mouseX,mouseY,ch);
|
rChildList.Message(rawEvent,event,mouseX,mouseY,ch); //rChildList does the work of passing the event correctly
|
||||||
}
|
}
|
||||||
|
|
||||||
void GContainer::Show()
|
void GContainer::Show()
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of GewiEngine.
|
\brief Implementation of GewiEngine.
|
||||||
|
|
||||||
Implementation of GewiEngine, core engine for Gewi GUI control.
|
Implementation of GewiEngine, core engine for Gewi GUI control.
|
||||||
<br>$Id: GewiEngine.cpp,v 1.7 2003/06/11 00:19:29 cozman Exp $<br>
|
<br>$Id: GewiEngine.cpp,v 1.8 2003/06/12 09:32:33 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ namespace Gewi
|
|||||||
{
|
{
|
||||||
|
|
||||||
VersionInfo GewiEngine::Version(0,2,0,"dev");
|
VersionInfo GewiEngine::Version(0,2,0,"dev");
|
||||||
VersionInfo GewiEngine::MinZEVersion(0,8,4,"dev");
|
VersionInfo GewiEngine::MinZEVersion(0,8,4,"dev"); //important to keep this accurate
|
||||||
GewiEngine *GewiEngine::sInstance=NULL;
|
GewiEngine *GewiEngine::sInstance=NULL;
|
||||||
|
|
||||||
GewiEngine::GewiEngine()
|
GewiEngine::GewiEngine()
|
||||||
@ -40,7 +40,7 @@ GewiEngine::GewiEngine()
|
|||||||
|
|
||||||
ze->SetEventFilter((SDL_EventFilter)GewiEngine::EventFilter);
|
ze->SetEventFilter((SDL_EventFilter)GewiEngine::EventFilter);
|
||||||
SDL_EnableUNICODE(1); //needed for the key translation
|
SDL_EnableUNICODE(1); //needed for the key translation
|
||||||
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
|
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); //more like typing, less like game
|
||||||
}
|
}
|
||||||
|
|
||||||
GewiEngine* GewiEngine::GetInstance()
|
GewiEngine* GewiEngine::GetInstance()
|
||||||
@ -67,10 +67,11 @@ void GewiEngine::ReleaseInstance()
|
|||||||
|
|
||||||
int GewiEngine::EventFilter(SDL_Event *event)
|
int GewiEngine::EventFilter(SDL_Event *event)
|
||||||
{
|
{
|
||||||
static char noChar = static_cast<char>(0);
|
static char noChar = '\0';
|
||||||
GewiEngine *gewi = GewiEngine::GetInstance();
|
GewiEngine *gewi = GewiEngine::GetInstance();
|
||||||
char ch;
|
char ch;
|
||||||
|
|
||||||
|
//called inside ZEngine::CheckEvents
|
||||||
switch(event->type)
|
switch(event->type)
|
||||||
{
|
{
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
@ -93,28 +94,19 @@ int GewiEngine::EventFilter(SDL_Event *event)
|
|||||||
ch = TranslateKey(event->key.keysym);
|
ch = TranslateKey(event->key.keysym);
|
||||||
gewi->SendMessage(event,GE_KUP,0,0,ch);
|
gewi->SendMessage(event,GE_KUP,0,0,ch);
|
||||||
break;
|
break;
|
||||||
case SDL_QUIT:
|
|
||||||
GewiEngine::ReleaseInstance();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 1; //pass the event on
|
return 1; //pass the event on, allowing ZEngine to do what it needs
|
||||||
}
|
}
|
||||||
|
|
||||||
char GewiEngine::TranslateKey(SDL_keysym key)
|
char GewiEngine::TranslateKey(SDL_keysym key)
|
||||||
{
|
{
|
||||||
char ch;
|
//this is why unicode must be enabled, without this it'd be one massive switch statement
|
||||||
|
if(key.unicode > 0 && key.unicode <= 255)
|
||||||
if(key.unicode && key.unicode <= 255)
|
return static_cast<char>(key.unicode);
|
||||||
ch = static_cast<char>(key.unicode);
|
|
||||||
else
|
else
|
||||||
ch = static_cast<char>(127);
|
return static_cast<char>(127);
|
||||||
|
|
||||||
if(ch >= 'a' && ch <= 'z' && (key.mod & KMOD_SHIFT))
|
|
||||||
ch -= 20; //capitalize
|
|
||||||
|
|
||||||
return ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GewiEngine::Display()
|
void GewiEngine::Display()
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of GSlider, GHorizSlider and GVertSlider.
|
\brief Implementation of GSlider, GHorizSlider and GVertSlider.
|
||||||
|
|
||||||
Implementation of GSlider, GHorizSlider and GVertSlider, the slide-select classes for Gewi.
|
Implementation of GSlider, GHorizSlider and GVertSlider, the slide-select classes for Gewi.
|
||||||
<br>$Id: GewiSlider.cpp,v 1.4 2003/06/07 05:42:33 cozman Exp $<br>
|
<br>$Id: GewiSlider.cpp,v 1.5 2003/06/12 09:32:33 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -58,9 +58,10 @@ void GSlider::SetPos(float pos)
|
|||||||
pos = static_cast<float>(rounded-rounded%rIncrement); //snap to a multiple of increment
|
pos = static_cast<float>(rounded-rounded%rIncrement); //snap to a multiple of increment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//get within bounds
|
||||||
if(pos < rMin)
|
if(pos < rMin)
|
||||||
pos = rMin;
|
pos = rMin;
|
||||||
if(pos > rMax)
|
else if(pos > rMax)
|
||||||
pos = rMax;
|
pos = rMax;
|
||||||
rPos = pos;
|
rPos = pos;
|
||||||
}
|
}
|
||||||
@ -90,7 +91,7 @@ void GHorizSlider::Show()
|
|||||||
if(rPressed && !rZE->LButtonPressed() || !MouseInWidget()) //dont allow them to drag pointer out of box
|
if(rPressed && !rZE->LButtonPressed() || !MouseInWidget()) //dont allow them to drag pointer out of box
|
||||||
Message(NULL,GE_LUP,rZE->MouseX(),rZE->MouseY(),static_cast<char>(0)); //fake a message
|
Message(NULL,GE_LUP,rZE->MouseX(),rZE->MouseY(),static_cast<char>(0)); //fake a message
|
||||||
|
|
||||||
//the slider is centered about the current position
|
//the slider is centered about the current position, altered if currently sliding
|
||||||
if(rPressed)
|
if(rPressed)
|
||||||
xPos = rZE->MouseX()-rGewi->Image(rSlider)->Width()/2.0f;
|
xPos = rZE->MouseX()-rGewi->Image(rSlider)->Width()/2.0f;
|
||||||
else
|
else
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of GStaticText.
|
\brief Implementation of GStaticText.
|
||||||
|
|
||||||
Implementation of GStaticText, file to hold static text, labels and such.
|
Implementation of GStaticText, file to hold static text, labels and such.
|
||||||
<br>$Id: GewiStaticText.cpp,v 1.5 2003/06/11 00:19:29 cozman Exp $<br>
|
<br>$Id: GewiStaticText.cpp,v 1.6 2003/06/12 09:32:33 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -37,7 +37,6 @@ void GStaticText::Create(float x, float y, float width, float height,
|
|||||||
ResourceID font, std::string text, GewiJustify justify, ResourceID backgroundImg)
|
ResourceID font, std::string text, GewiJustify justify, ResourceID backgroundImg)
|
||||||
{
|
{
|
||||||
GWidget::Create(x,y,width,height);
|
GWidget::Create(x,y,width,height);
|
||||||
|
|
||||||
rBackgroundImage = backgroundImg;
|
rBackgroundImage = backgroundImg;
|
||||||
rFont = font;
|
rFont = font;
|
||||||
rJustify = justify; //must justify pre-SetText
|
rJustify = justify; //must justify pre-SetText
|
||||||
@ -51,12 +50,12 @@ void GStaticText::Message(SDL_Event *rawEvent, GewiEvent event, Uint16 mouseX, U
|
|||||||
|
|
||||||
void GStaticText::Show()
|
void GStaticText::Show()
|
||||||
{
|
{
|
||||||
//images must call Resize with each draw (shared resources)
|
//images must call Resize with each draw (see shared resources rant)
|
||||||
if(rBackgroundImage != GewiEngine::InvalidID)
|
if(rBackgroundImage != GewiEngine::InvalidID)
|
||||||
|
{
|
||||||
rGewi->Image(rBackgroundImage)->Resize(static_cast<unsigned int>(rBoundRect.Width()),static_cast<unsigned int>(rBoundRect.Height()));
|
rGewi->Image(rBackgroundImage)->Resize(static_cast<unsigned int>(rBoundRect.Width()),static_cast<unsigned int>(rBoundRect.Height()));
|
||||||
|
|
||||||
if(rBackgroundImage != GewiEngine::InvalidID)
|
|
||||||
rGewi->Image(rBackgroundImage)->Draw(rBoundRect.X(),rBoundRect.Y());
|
rGewi->Image(rBackgroundImage)->Draw(rBoundRect.X(),rBoundRect.Y());
|
||||||
|
}
|
||||||
rTextBuf.Draw(rBoundRect.X()+rXOff,rBoundRect.Y()+rYOff); //draw text shifted by offset
|
rTextBuf.Draw(rBoundRect.X()+rXOff,rBoundRect.Y()+rYOff); //draw text shifted by offset
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,27 +70,21 @@ void GStaticText::SetText(std::string text)
|
|||||||
w=rTextBuf.Width();
|
w=rTextBuf.Width();
|
||||||
h=rTextBuf.Height();
|
h=rTextBuf.Height();
|
||||||
|
|
||||||
//center each by default
|
//left,right,center
|
||||||
rXOff = static_cast<int>(rBoundRect.Width()-w)/2;
|
|
||||||
rYOff = static_cast<int>(rBoundRect.Height()-h)/2;
|
|
||||||
|
|
||||||
if(rJustify & GJ_LEFT)
|
if(rJustify & GJ_LEFT)
|
||||||
{
|
|
||||||
rXOff = 0;
|
rXOff = 0;
|
||||||
}
|
|
||||||
else if(rJustify & GJ_RIGHT)
|
else if(rJustify & GJ_RIGHT)
|
||||||
{
|
|
||||||
rXOff = static_cast<int>(rBoundRect.Width()-w);
|
rXOff = static_cast<int>(rBoundRect.Width()-w);
|
||||||
}
|
else
|
||||||
|
rXOff = static_cast<int>(rBoundRect.Width()-w)/2;
|
||||||
|
|
||||||
|
//top,bottom,center
|
||||||
if(rJustify & GJ_TOP)
|
if(rJustify & GJ_TOP)
|
||||||
{
|
|
||||||
rYOff = 0;
|
rYOff = 0;
|
||||||
}
|
|
||||||
else if(rJustify & GJ_BOTTOM)
|
else if(rJustify & GJ_BOTTOM)
|
||||||
{
|
|
||||||
rYOff = static_cast<int>(rBoundRect.Height()-h);
|
rYOff = static_cast<int>(rBoundRect.Height()-h);
|
||||||
}
|
else
|
||||||
|
rYOff = static_cast<int>(rBoundRect.Height()-h)/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GStaticText::GetText()
|
std::string GStaticText::GetText()
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of GTextField.
|
\brief Implementation of GTextField.
|
||||||
|
|
||||||
Implementation of GTextField, text input area widget.
|
Implementation of GTextField, text input area widget.
|
||||||
<br>$Id: GewiTextField.cpp,v 1.5 2003/06/11 00:19:29 cozman Exp $<br>
|
<br>$Id: GewiTextField.cpp,v 1.6 2003/06/12 09:32:33 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ void GTextField::Message(SDL_Event *rawEvent, GewiEvent event, Uint16 mouseX, Ui
|
|||||||
else if(ch == '\b')
|
else if(ch == '\b')
|
||||||
rText = rText.length() ? rText.substr(0,rText.length()-1) : ""; //go back one character
|
rText = rText.length() ? rText.substr(0,rText.length()-1) : ""; //go back one character
|
||||||
|
|
||||||
rGewi->Font(rFont)->DrawText(rText.length() ? rText : " ",rBuffer);
|
rGewi->Font(rFont)->DrawText(rText.length() ? rText : "",rBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of GWidget.
|
\brief Implementation of GWidget.
|
||||||
|
|
||||||
Implementation of GWidget, virtual widget base class.
|
Implementation of GWidget, virtual widget base class.
|
||||||
<br>$Id: GewiWidget.cpp,v 1.6 2003/06/11 00:19:29 cozman Exp $<br>
|
<br>$Id: GewiWidget.cpp,v 1.7 2003/06/12 09:32:33 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -40,6 +40,7 @@ GWidget::GWidget(GContainer *parent) :
|
|||||||
rRelY(0),
|
rRelY(0),
|
||||||
rVisible(true)
|
rVisible(true)
|
||||||
{
|
{
|
||||||
|
//widgets take care of all registration, making the parent processes virtually hidden
|
||||||
if(rParent)
|
if(rParent)
|
||||||
rParent->AddChild(this);
|
rParent->AddChild(this);
|
||||||
else
|
else
|
||||||
@ -84,6 +85,7 @@ bool GWidget::Visible()
|
|||||||
return rVisible;
|
return rVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//it is important to remember rBoundRect is the actual position
|
||||||
bool GWidget::MouseInWidget()
|
bool GWidget::MouseInWidget()
|
||||||
{
|
{
|
||||||
return rZE->MouseInRect(&rBoundRect.SDLrect());
|
return rZE->MouseInRect(&rBoundRect.SDLrect());
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
\brief Implementation of WidgetList.
|
\brief Implementation of WidgetList.
|
||||||
|
|
||||||
Implementation of WidgetList, a list of widgets used by GewiEngine and GContainers.
|
Implementation of WidgetList, a list of widgets used by GewiEngine and GContainers.
|
||||||
<br>$Id: GewiWidgetList.cpp,v 1.4 2003/06/09 03:28:43 cozman Exp $<br>
|
<br>$Id: GewiWidgetList.cpp,v 1.5 2003/06/12 09:32:33 cozman Exp $<br>
|
||||||
\author James Turk
|
\author James Turk
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -30,6 +30,8 @@ WidgetNode::WidgetNode() :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//WidgetList keeps circular list of nodes, backwards traversal is key for proper draw order//
|
||||||
|
|
||||||
void WidgetList::DeleteWidgetMem(WidgetNode *node)
|
void WidgetList::DeleteWidgetMem(WidgetNode *node)
|
||||||
{
|
{
|
||||||
if(node == mWidgetList) //special case if deleting top node
|
if(node == mWidgetList) //special case if deleting top node
|
||||||
@ -39,7 +41,7 @@ void WidgetList::DeleteWidgetMem(WidgetNode *node)
|
|||||||
else
|
else
|
||||||
mWidgetList = NULL;
|
mWidgetList = NULL;
|
||||||
}
|
}
|
||||||
//adjust links and actually delete node
|
//adjust links & delete node
|
||||||
node->prev->next = node->next;
|
node->prev->next = node->next;
|
||||||
node->next->prev = node->prev;
|
node->next->prev = node->prev;
|
||||||
delete node;
|
delete node;
|
||||||
@ -55,11 +57,11 @@ void WidgetList::AddWidget(WidgetNode *node)
|
|||||||
{
|
{
|
||||||
if(mWidgetList == NULL)
|
if(mWidgetList == NULL)
|
||||||
{
|
{
|
||||||
node->next = node->prev = node;
|
node->next = node->prev = node; //first node points to self in both directions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//make connections
|
//make front & back connections
|
||||||
node->next = mWidgetList;
|
node->next = mWidgetList;
|
||||||
node->prev = mWidgetList->prev;
|
node->prev = mWidgetList->prev;
|
||||||
mWidgetList->prev->next = node;
|
mWidgetList->prev->next = node;
|
||||||
@ -80,19 +82,17 @@ void WidgetList::DeleteWidget(GWidget *widget)
|
|||||||
if(cur->widget == widget)
|
if(cur->widget == widget)
|
||||||
found = cur;
|
found = cur;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
} while(cur != mWidgetList && !found);
|
} while(cur != mWidgetList && !found); //go through & find node
|
||||||
|
|
||||||
if(found)
|
if(found)
|
||||||
{
|
|
||||||
DeleteWidgetMem(found);
|
DeleteWidgetMem(found);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetList::DeleteWidgets()
|
void WidgetList::DeleteWidgets()
|
||||||
{
|
{
|
||||||
WidgetNode *cur = mWidgetList;
|
WidgetNode *cur = mWidgetList;
|
||||||
while(mWidgetList)
|
while(mWidgetList) //will be set to null on last widget
|
||||||
{
|
{
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
DeleteWidgetMem(cur->prev);
|
DeleteWidgetMem(cur->prev);
|
||||||
@ -172,7 +172,7 @@ void WidgetList::ShowWidgets()
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
cur = cur->prev; //draw from back to front, through list in reverse
|
cur = cur->prev; //draw from back to front, through list in reverse
|
||||||
if(cur->widget->Visible())
|
if(cur->widget->Visible()) //visible checked here so each Show() doesn't need to bother
|
||||||
cur->widget->Show();
|
cur->widget->Show();
|
||||||
}while(cur != mWidgetList);
|
}while(cur != mWidgetList);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ void Test1()
|
|||||||
ZImage bg,temp[8];
|
ZImage bg,temp[8];
|
||||||
ZFont font;
|
ZFont font;
|
||||||
ResourceID id[8],fontID;
|
ResourceID id[8],fontID;
|
||||||
|
//all of the widgets//
|
||||||
GWindow window;
|
GWindow window;
|
||||||
GTextButton txtButton;
|
GTextButton txtButton;
|
||||||
GTextField txtField,txtField2(&window);
|
GTextField txtField,txtField2(&window);
|
||||||
@ -53,6 +54,7 @@ void Test1()
|
|||||||
bg.Open("data/rainbow.bmp");
|
bg.Open("data/rainbow.bmp");
|
||||||
bg.Resize(ze->Width(),ze->Height());
|
bg.Resize(ze->Width(),ze->Height());
|
||||||
|
|
||||||
|
//opening the images//
|
||||||
temp[0].Open("data/b1.bmp");
|
temp[0].Open("data/b1.bmp");
|
||||||
temp[1].Open("data/b2.bmp");
|
temp[1].Open("data/b2.bmp");
|
||||||
temp[2].Open("data/skin1.bmp");
|
temp[2].Open("data/skin1.bmp");
|
||||||
@ -63,6 +65,7 @@ void Test1()
|
|||||||
temp[7].Open("data/slider2.bmp");
|
temp[7].Open("data/slider2.bmp");
|
||||||
font.Open("data/axaxax.ttf",20);
|
font.Open("data/axaxax.ttf",20);
|
||||||
|
|
||||||
|
//registering the resources//
|
||||||
for(int i=0; i < 8; ++i)
|
for(int i=0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
temp[i].SetColorKey(255,0,255);
|
temp[i].SetColorKey(255,0,255);
|
||||||
@ -70,6 +73,7 @@ void Test1()
|
|||||||
}
|
}
|
||||||
fontID = gewi->AddResource(&font);
|
fontID = gewi->AddResource(&font);
|
||||||
|
|
||||||
|
//each widget must be created//
|
||||||
window.Create(300,300,300,300,id[2]);
|
window.Create(300,300,300,300,id[2]);
|
||||||
button.Create(50,30,10,10,id[0],id[1]);
|
button.Create(50,30,10,10,id[0],id[1]);
|
||||||
txtField.Create(100,100,500,50,fontID,id[3],20,20);
|
txtField.Create(100,100,500,50,fontID,id[3],20,20);
|
||||||
@ -98,7 +102,7 @@ void Test1()
|
|||||||
temp[2].SetAlpha(63+hSlider.GetPos()*64);
|
temp[2].SetAlpha(63+hSlider.GetPos()*64);
|
||||||
|
|
||||||
bg.Draw(0,0);
|
bg.Draw(0,0);
|
||||||
gewi->Display();
|
gewi->Display(); //draws everything
|
||||||
ze->Update();
|
ze->Update();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user