// $Id: TGHtmlForm.cxx,v 1.3 2007/05/18 16:00:28 brun Exp $
// Author: Valeriy Onuchin 03/05/2007
/*************************************************************************
* Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
HTML widget for xclass. Based on tkhtml 1.28
Copyright (C) 1997-2000 D. Richard Hipp
Copyright (C) 2002-2003 Hector Peraza.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************/
// Routines used for processing HTML makeup for forms.
#include
#include
#include
#include "TGHtml.h"
#include "TGButton.h"
#include "TGTextEntry.h"
#include "TGListBox.h"
#include "TGTextEdit.h"
#include "TGComboBox.h"
////////////////////////////////////////////////////////////////////////////////
/// Unmap any input control that is currently mapped.
void TGHtml::UnmapControls()
{
TGHtmlInput *p;
for (p = fFirstInput; p; p = p->fINext) {
if (p->fFrame != 0 /*&& p->fFrame->IsMapped()*/) {
p->fFrame->UnmapWindow();
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// Map any control that should be visible according to the
/// current scroll position. At the same time, if any controls that
/// should not be visible are mapped, unmap them. After this routine
/// finishes, all controls should be in their proper places
/// regardless of where they might have been before.
///
/// Return the number of controls that are currently visible.
int TGHtml::MapControls()
{
TGHtmlInput *p; // For looping over all controls
int x, y, w, h; // Part of the virtual canvas that is visible
int cnt = 0; // Number of visible controls
x = fVisible.fX;
y = fVisible.fY;
w = fCanvas->GetWidth();
h = fCanvas->GetHeight();
for (p = fFirstInput; p; p = p->fINext) {
if (p->fFrame == 0) continue;
if (p->fY < y + h && p->fY + p->fH > y &&
p->fX < x + w && p->fX + p->fW > x) {
// The control should be visible. Make is so if it isn't already
p->fFrame->MoveResize(p->fX - x, p->fY + fFormPadding/2 - y,
p->fW, p->fH - fFormPadding);
/*if (!p->fFrame->IsMapped())*/ p->fFrame->MapWindow();
++cnt;
} else {
// This control should not be visible. Unmap it.
/*if (p->fFrame->IsMapped())*/ p->fFrame->UnmapWindow();
}
}
return cnt;
}
////////////////////////////////////////////////////////////////////////////////
/// Delete all input controls. This happens when the TGHtml widget
/// is cleared.
void TGHtml::DeleteControls()
{
TGHtmlInput *p; // For looping over all controls
p = fFirstInput;
fFirstInput = 0;
fLastInput = 0;
fNInput = 0;
if (p == 0) return;
for (; p; p = p->fINext) {
if (p->fPForm && ((TGHtmlForm *)p->fPForm)->fHasctl) {
((TGHtmlForm *)p->fPForm)->fHasctl = 0;
}
if (p->fFrame) {
if (!fExiting) p->fFrame->DestroyWindow();
delete p->fFrame;
p->fFrame = 0;
}
p->fSized = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
/// Return an appropriate type value for the given markup.
static int InputType(TGHtmlElement *p)
{
int type = INPUT_TYPE_Unknown;
const char *z;
int i;
static struct {
const char *zName;
int type;
} types[] = {
{ "checkbox", INPUT_TYPE_Checkbox },
{ "file", INPUT_TYPE_File },
{ "hidden", INPUT_TYPE_Hidden },
{ "image", INPUT_TYPE_Image },
{ "password", INPUT_TYPE_Password },
{ "radio", INPUT_TYPE_Radio },
{ "reset", INPUT_TYPE_Reset },
{ "submit", INPUT_TYPE_Submit },
{ "text", INPUT_TYPE_Text },
{ "name", INPUT_TYPE_Text },
{ "textfield", INPUT_TYPE_Text },
{ "button", INPUT_TYPE_Button },
{ "name", INPUT_TYPE_Text },
};
switch (p->fType) {
case Html_INPUT:
z = p->MarkupArg("type", "text");
if (z == 0) break;
for (i = 0; i < int(sizeof(types) / sizeof(types[0])); i++) {
if (strcasecmp(types[i].zName, z) == 0) {
type = types[i].type;
break;
}
}
break;
case Html_SELECT:
type = INPUT_TYPE_Select;
break;
case Html_TEXTAREA:
type = INPUT_TYPE_TextArea;
break;
case Html_APPLET:
case Html_IFRAME:
case Html_EMBED:
type = INPUT_TYPE_Applet;
break;
default:
CANT_HAPPEN;
break;
}
return type;
}
////////////////////////////////////////////////////////////////////////////////
/// 'frame' is the child widget that is used to implement an input
/// element. Query the widget for its size and put that information
/// in the pElem structure that represents the input.
void TGHtml::SizeAndLink(TGFrame *frame, TGHtmlInput *pElem)
{
pElem->fFrame = frame;
if (pElem->fFrame == 0) {
pElem->Empty();
} else if (pElem->fItype == INPUT_TYPE_Hidden) {
pElem->fW = 0;
pElem->fH = 0;
pElem->fFlags &= ~HTML_Visible;
pElem->fStyle.fFlags |= STY_Invisible;
} else {
pElem->fW = frame->GetDefaultWidth();
pElem->fH = frame->GetDefaultHeight() + fFormPadding;
pElem->fFlags |= HTML_Visible;
pElem->fHtml = this;
}
pElem->fINext = 0;
if (fFirstInput == 0) {
fFirstInput = pElem;
} else {
fLastInput->fINext = pElem;
}
fLastInput = pElem;
pElem->fSized = 1;
#if 0
if (pElem->fFrame) {
pElem->fFrame->ChangeOptions(pElem->fFrame->GetOptions() | kOwnBackground);
pElem->fFrame->SetBackgroundColor(_defaultFrameBackground);
}
#else
if (pElem->fFrame) {
int bg = pElem->fStyle.fBgcolor;
//int fg = pElem->fStyle.color;
ColorStruct_t *cbg = fApColor[bg];
//ColorStruct_t *cfg = fApColor[fg];
pElem->fFrame->ChangeOptions(pElem->fFrame->GetOptions() | kOwnBackground);
pElem->fFrame->SetBackgroundColor(cbg->fPixel);
}
#endif
if (pElem->fFrame) {
// the following is needed by some embedded widgets like
// TGListBox and TGTextEdit
pElem->fFrame->MapSubwindows();
pElem->fFrame->Layout();
}
}
////////////////////////////////////////////////////////////////////////////////
/// Append all text and space tokens between pStart and pEnd to
/// the given TString. [ TGTextEdit ]
void TGHtml::AppendText(TGString *str, TGHtmlElement *pFirs,
TGHtmlElement *pEnd)
{
while (pFirs && pFirs != pEnd) {
switch (pFirs->fType) {
case Html_Text:
str->Append(((TGHtmlTextElement *)pFirs)->fZText);
break;
case Html_Space:
if (pFirs->fFlags & HTML_NewLine) {
str->Append("\n");
} else {
int cnt;
static char zSpaces[] = " ";
cnt = pFirs->fCount;
while (cnt > (int)sizeof(zSpaces) - 1) {
str->Append(zSpaces, sizeof(zSpaces) - 1);
cnt -= sizeof(zSpaces) - 1;
}
if (cnt > 0) {
str->Append(zSpaces, cnt);
}
}
break;
default:
break;
}
pFirs = pFirs->fPNext;
}
}
class TGHtmlLBEntry : public TGTextLBEntry {
public:
TGHtmlLBEntry(const TGWindow *p, TGString *s, TGString *val, int ID) :
TGTextLBEntry(p, s, ID) { fVal = val; }
virtual ~TGHtmlLBEntry() { if (fVal) delete fVal; }
const char *GetValue() const { return fVal ? fVal->GetString() : 0; }
protected:
TGString *fVal;
};
////////////////////////////////////////////////////////////////////////////////
/// The "p" argument points to a ) looking for
///