listbox fixes

This commit is contained in:
Peter Schojer 2008-09-26 09:23:43 +00:00
parent 585a7f147b
commit 22e337614c
17 changed files with 1608 additions and 1250 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="ExtJS"
ProjectGUID="{19FA461F-7419-4653-8A6B-B93002F7DB14}"
RootNamespace="ExtJS"
@ -53,7 +53,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
CompileAs="0"
/>
@ -76,7 +75,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\bin\Poco$(ProjectName)d.pdb"
SubSystem="1"
OptimizeForWindows98="1"
OptimizeForWindows98="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="..\..\lib\Poco$(ProjectName)d.lib"
@ -145,7 +144,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="0"
CompileAs="0"
/>
@ -170,7 +168,7 @@
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
OptimizeForWindows98="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="..\..\lib\Poco$(ProjectName).lib"

View File

@ -42,12 +42,17 @@
#include "Poco/WebWidgets/ExtJS/ExtJS.h"
#include "Poco/WebWidgets/Renderer.h"
#include "Poco/WebWidgets/JSDelegate.h"
namespace Poco {
namespace Net {
class HTTPServerResponse;
}
namespace WebWidgets {
class ListBoxCell;
class ListBox;
namespace ExtJS {
@ -56,6 +61,9 @@ class ExtJS_API ListBoxCellRenderer: public Poco::WebWidgets::Renderer
/// ListBoxCellRenderer renders a button
{
public:
static const std::string EV_ROWSELECT;
static const std::string EV_ROWDESELECT;
ListBoxCellRenderer();
/// Creates the ListBoxCellRenderer.
@ -70,6 +78,14 @@ public:
static void renderProperties(const ListBoxCell* pCell, std::ostream& ostr);
/// Renders button properties
static Poco::WebWidgets::JSDelegate createRowSelectionServerCallback(const ListBox* pList);
static void onBeforeLoad(void* pSender, std::pair<ListBoxCell*, Poco::Net::HTTPServerResponse*>& ld);
static Poco::WebWidgets::JSDelegate createAfterLoadServerCallback(const ListBox* pList);
/// Adds a javascript callback to inform the WebServer that the client has finished loading data
/// Method signature is ( Store this, Ext.data.Record[] records, Object options )
};

View File

@ -41,6 +41,7 @@
#include "Poco/WebWidgets/Button.h"
#include "Poco/WebWidgets/RequestHandler.h"
#include "Poco/WebWidgets/WebApplication.h"
#include "Poco/WebWidgets/WebWidgetsException.h"
#include "Poco/NumberFormatter.h"
@ -89,6 +90,8 @@ void ButtonCellRenderer::renderProperties(const ButtonCell* pButtonCell, const s
{
ostr << "type:'submit',";
Form::Ptr pForm = Utility::insideForm(pButtonCell);
if (!pForm)
throw WebWidgetsException("SubmitButton must be used inside a form!");
ostr << "handler: function(){Ext.getCmp('" << pForm->id() << "').getForm().submit();},";
}
View* pView = pButtonCell->getOwner();

View File

@ -36,8 +36,15 @@
#include "Poco/WebWidgets/ExtJS/ListBoxCellRenderer.h"
#include "Poco/WebWidgets/ExtJS/FormRenderer.h"
#include "Poco/WebWidgets/ExtJS/TableRenderer.h"
#include "Poco/WebWidgets/ExtJS/Utility.h"
#include "Poco/WebWidgets/ListBoxCell.h"
#include "Poco/WebWidgets/ListBox.h"
#include "Poco/WebWidgets/RequestHandler.h"
#include "Poco/WebWidgets/Table.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Delegate.h"
#include "Poco/NumberFormatter.h"
#include <sstream>
@ -46,6 +53,10 @@ namespace WebWidgets {
namespace ExtJS {
const std::string ListBoxCellRenderer::EV_ROWSELECT("rowselect");
const std::string ListBoxCellRenderer::EV_ROWDESELECT("rowdeselect");
ListBoxCellRenderer::ListBoxCellRenderer()
{
}
@ -77,45 +88,123 @@ void ListBoxCellRenderer::renderBody(const Renderable* pRenderable, const Render
void ListBoxCellRenderer::renderProperties(const ListBoxCell* pListBoxCell, std::ostream& ostr)
{
Utility::writeRenderableProperties(pListBoxCell, ostr);
Utility::writeCellProperties(pListBoxCell, ostr);
if (pListBoxCell->getHeight() > 0)
ostr << ",height:" << pListBoxCell->getHeight();
if (pListBoxCell->getWidth() > 0)
ostr << ",width:" << pListBoxCell->getWidth();
const View* pOwner = pListBoxCell->getOwner();
poco_check_ptr (pOwner);
const ListBox* pList = dynamic_cast<const ListBox*>(pOwner);
if (pOwner->hasPosition())
ostr << ",x:" << pOwner->getPosition().posX << ",y:" << pOwner->getPosition().posY;
ostr << ",dataFields:['i','d'],data:[";
if (pList)
{
bool hasListeners = (pList->rowDeselected.hasJavaScriptCode() ||
pList->rowSelected.hasJavaScriptCode());
if (hasListeners)
{
ostr << ",listeners:{";
bool comma = false;
if (pList->rowDeselected.hasJavaScriptCode())
comma = Utility::writeJSEvent(ostr, EV_ROWDESELECT, pList->rowDeselected, &ListBoxCellRenderer::createRowSelectionServerCallback, pList);
if (pList->rowDeselected.hasJavaScriptCode())
{
if (comma) ostr << ",";
comma = Utility::writeJSEvent(ostr, EV_ROWSELECT, pList->rowSelected, &ListBoxCellRenderer::createRowSelectionServerCallback, pList);
}
ostr << "}";
}
}
// store: afterLoad, beforeLaod event
ostr << ",store:new Ext.data.SimpleStore({autoLoad:true,fields:[{name:'i'},{name:'d'}]";
ostr << ",proxy:new Ext.data.HttpProxy({url:";
std::map<std::string, std::string> addParams;
addParams.insert(std::make_pair(RequestHandler::KEY_EVID, ListBoxCell::EV_LOADDATA));
std::string url(Utility::createURI(addParams, pList->id()));
ostr << url << "})";
ostr << ",reader:new Ext.data.ArrayReader()";
if (pList->afterLoad.hasJavaScriptCode())
{
ostr << ",listeners:{";
Utility::writeJSEvent(ostr, Table::EV_AFTERLOAD, pList->afterLoad, &ListBoxCellRenderer::createAfterLoadServerCallback, pList);
ostr << "}";
}
ostr << "})";
ostr << ",dataFields:['i','d'],initVal:'";
//now serialize data, use cached content for that
ListBoxCell::StringData::const_iterator it = pListBoxCell->beginString();
ListBoxCell::StringData::const_iterator itEnd = pListBoxCell->endString();
ListBoxCell::Data::const_iterator itV = pListBoxCell->begin();
ListBoxCell::Data::const_iterator itVEnd = pListBoxCell->end();
int cnt = 0;
bool selected=false;
std::ostringstream initValue;
initValue << "'";
for (; it != itEnd; ++it, ++cnt, ++itV)
int cnt(0);
for (; itV != itVEnd; ++itV, ++cnt)
{
if (it != pListBoxCell->beginString())
ostr << ",";
if (itV->second)
{
if (selected)
initValue << ",";
initValue << cnt;
ostr << ",";
ostr << cnt;
selected = true;
}
}
ostr << "'";
ostr << ",valueField:'i',displayField:'d'";
ListBoxCell* pL = const_cast<ListBoxCell*>(pListBoxCell);
pL->beforeLoad += Poco::delegate(&ListBoxCellRenderer::onBeforeLoad);
WebApplication::instance().registerAjaxProcessor(Poco::NumberFormatter::format(pList->id()), pL);
if (!pOwner->getName().empty())
{
WebApplication::instance().registerFormProcessor(pOwner->getName(), pL);
}
}
Poco::WebWidgets::JSDelegate ListBoxCellRenderer::createRowSelectionServerCallback(const ListBox* pList)
{
// rowselect : ( Ext.ux.Multiselect field, Int idx, bool selected )
static const std::string signature("function(field,idx,sel)");
std::map<std::string, std::string> addParams;
addParams.insert(std::make_pair(ListBoxCell::ARG_ROW, "+idx"));
addParams.insert(std::make_pair(ListBoxCell::ARG_SELECTED, "+(sel?'1':'0')"));
addParams.insert(std::make_pair(RequestHandler::KEY_EVID, ListBoxCell::EV_ROWSELECTED));
return Utility::createServerCallback(signature, addParams, pList->id(), pList->rowSelected.getOnSuccess(), pList->rowSelected.getOnFailure());
}
Poco::WebWidgets::JSDelegate ListBoxCellRenderer::createAfterLoadServerCallback(const ListBox* pList)
{
poco_check_ptr (pList);
static const std::string signature("function(aStore, recs, op)");
std::map<std::string, std::string> addParams;
addParams.insert(std::make_pair(RequestHandler::KEY_EVID, ListBoxCell::EV_AFTERLOAD));
return Utility::createServerCallback(signature, addParams, pList->id(), pList->afterLoad.getOnSuccess(), pList->afterLoad.getOnFailure());
}
void ListBoxCellRenderer::onBeforeLoad(void* pSender, std::pair<ListBoxCell*, Poco::Net::HTTPServerResponse*>& ld)
{
ld.second->setChunkedTransferEncoding(true);
ld.second->setContentType("text/javascript");
std::ostream& ostr = ld.second->send();
//[
// ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
// ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am']
//]
ostr << "[";
ListBoxCell::StringData::const_iterator it = ld.first->beginString();
ListBoxCell::StringData::const_iterator itEnd = ld.first->endString();
int cnt = 0;
for (; it != itEnd; ++it, ++cnt)
{
if (it != ld.first->beginString())
ostr << ",";
ostr << "['" << cnt << "','" << *it << "']";
}
initValue << "'";
ostr << "]";
ostr << ",valueField:'i',displayField:'d',initVal:" << initValue.str();
}

View File

@ -170,7 +170,6 @@ Poco::WebWidgets::JSDelegate TableRenderer::createAfterLoadServerCallback(const
}
Poco::WebWidgets::JSDelegate TableRenderer::createRenderServerCallback(const Table* pTable)
{
poco_check_ptr (pTable);

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="TestSuite"
ProjectGUID="{AB43A995-70FA-4297-BD01-6C88938AA86D}"
Keyword="Win32Proj"
@ -52,7 +52,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
@ -139,7 +138,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,19 @@
.ux-mselect{
overflow:auto;
background:white;
position:relative; /* for calculating scroll offsets */
zoom:1;
overflow:auto;
}
.ux-mselect-item{
font:normal 12px tahoma, arial, helvetica, sans-serif;
padding:2px;
border:1px solid #fff;
white-space: nowrap;
cursor:pointer;
}
.ux-mselect-selected{
border:1px dotted #a3bae9 !important;
background:#DFE8F6;
cursor:pointer;
}
.ux-mselect{
overflow:auto;
background:white;
position:relative; /* for calculating scroll offsets */
zoom:1;
overflow:auto;
}
.ux-mselect-item{
font:normal 12px tahoma, arial, helvetica, sans-serif;
padding:2px;
border:1px solid #fff;
white-space: nowrap;
cursor:pointer;
}
.ux-mselect-selected{
border:1px dotted #a3bae9 !important;
background:#DFE8F6;
cursor:pointer;
}

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,7 @@
#include "Poco/WebWidgets/SimpleTableModel.h"
#include "Poco/WebWidgets/JSDelegate.h"
#include "Poco/WebWidgets/ResourceManager.h"
#include "Poco/WebWidgets/SubmitButton.h"
#include "Poco/TeeStream.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTime.h"
@ -1127,6 +1128,39 @@ void ExtJSTest::testListBox()
}
void ExtJSTest::testFormListBox()
{
ResourceManager::Ptr pRM(new ResourceManager());Utility::initialize(pRM, Poco::Path());WebApplication webApp(Poco::URI("/"), pRM);
LookAndFeel::Ptr laf(new LookAndFeel());
webApp.setLookAndFeel(laf);
RenderContext context(*laf, webApp);
Utility::initialize(laf);
Page::Ptr ptr = new Page("test");
webApp.setCurrentPage(ptr);
Form::Ptr ptrF = new Form(Poco::URI("/test"));
ptrF->setHeight(600);
ptrF->setWidth(800);
ptr->add(ptrF);
ListBox::Ptr ptrList(new ListBox("MyWindow"));
ptrList->setWidth(640);
ptrList->setHeight(400);
ptrF->add(ptrList);
ptrList->insert(std::string("First"), false);
ptrList->insert(std::string("FirstSelected"), true);
ptrList->insert(std::string("Second"), false);
ptrList->insert(std::string("SecondSelected"), true);
ptrF->add(new SubmitButton("", "Click"));
std::ostringstream ostr;
std::ofstream fstr("testFormListBox.html");
TeeOutputStream out(ostr);
out.addStream(fstr);
ptr->renderHead(context, out);
ptr->renderBody(context, out);
std::string result = ostr.str();
}
void ExtJSTest::testDateFormatConversion()
{
std::string result = Utility::convertPocoDateToPHPDate(Poco::DateTimeFormat::ISO8601_FORMAT);
@ -1606,6 +1640,7 @@ CppUnit::Test* ExtJSTest::suite()
CppUnit_addTest(pSuite, ExtJSTest, testFormFrameVerticalLayout);
CppUnit_addTest(pSuite, ExtJSTest, testFormGridLayoutNullElements);
CppUnit_addTest(pSuite, ExtJSTest, testFormImage);
CppUnit_addTest(pSuite, ExtJSTest, testFormListBox);
CppUnit_addTest(pSuite, ExtJSTest, testDateFormatConversion);
CppUnit_addTest(pSuite, ExtJSTest, testCollapsible);
CppUnit_addTest(pSuite, ExtJSTest, testCollapsible2);

View File

@ -68,6 +68,7 @@ public:
void testFormFrameHorizontalLayout();
void testFormFrameVerticalLayout();
void testFormImage();
void testFormListBox();
void testTabView();
void testCollapsible();
void testCollapsible2();

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="WebWidgets"
ProjectGUID="{8962DAD7-4F7B-46D0-A451-8D3476606890}"
RootNamespace="WebWidgets"
@ -53,7 +53,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
CompileAs="0"
/>
@ -76,7 +75,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\bin\Poco$(ProjectName)d.pdb"
SubSystem="1"
OptimizeForWindows98="1"
OptimizeForWindows98="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="..\lib\Poco$(ProjectName)d.lib"
@ -145,7 +144,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="0"
CompileAs="0"
/>
@ -170,7 +168,7 @@
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
OptimizeForWindows98="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="..\lib\Poco$(ProjectName).lib"

View File

@ -42,6 +42,8 @@
#include "Poco/WebWidgets/Control.h"
#include "Poco/WebWidgets/ListBoxCell.h"
#include "Poco/WebWidgets/JavaScriptEvent.h"
#include "Poco/FIFOEvent.h"
#include <vector>
@ -54,7 +56,16 @@ class WebWidgets_API ListBox: public Control
{
public:
typedef Poco::AutoPtr<ListBox> Ptr;
typedef ListBoxCell::Data Data; /// An element plus its selected flag as pair
typedef ListBoxCell::Data Data; /// An element plus its selected flag as std::pair
typedef ListBoxCell::RowValueChange RowValueChange; /// the row plus old and new value
FIFOEvent<Poco::Net::HTTPServerResponse*> beforeLoad; /// thrown whenever a load is requested, internal event to which the ListBoxCellRenderer must register
JavaScriptEvent<ListBox*> afterLoad; // thrown after data was loaded
JavaScriptEvent<int> rowSelected; /// fires the row selected event
JavaScriptEvent<int> rowDeselected; /// fires the row deselected event
ListBox(const std::string& name);
/// Creates a ListBox with the given name.
@ -62,18 +73,6 @@ public:
ListBox();
/// Creates an anonymous TextField.
void setHeight(int height);
/// Sets the height in pixel. A negative value equals autoSize.
int getHeight() const;
/// Returns the height in pixel. A negative value equals autoSize.
void setWidth(int width);
/// Sets the width in pixel. A negative value equals autoSize.
int getWidth() const;
/// Returns the width in pixel. A negative value equals autoSize.
Data::const_iterator begin() const;
/// ConstIterator to all elements
@ -104,6 +103,18 @@ public:
void deselect(const Any& elem);
/// Deselects the element.
void selectByIndex(int idx, bool sel = true);
/// Selects the element by Index. idx values that are out of range are ignored
void deselectByIndex(int idx);
/// Deselects the element. idx values that are out of range are ignored
void selectAll(bool sel= true);
/// Selects all elements
void deselectAll();
/// Deselects all elements
bool hasSelected() const;
/// Returns true if at least one selected element exists
@ -117,10 +128,10 @@ protected:
ListBox(const std::type_info& type);
/// Creates a ListBox.
ListBox(const std::string& name, const std::type_info& type, Cell::Ptr ptrCell);
ListBox(const std::string& name, const std::type_info& type, ListBoxCell::Ptr ptrCell);
/// Creates a ListBox and assigns it the given name.
ListBox(const std::type_info& type, Cell::Ptr ptrCell);
ListBox(const std::type_info& type, ListBoxCell::Ptr ptrCell);
/// Creates a ListBox.
~ListBox();
@ -131,6 +142,17 @@ protected:
void init(Cell::Ptr pCell);
/// Common init code for all ctors.
void fireBeforeLoad(std::pair<ListBoxCell*, Poco::Net::HTTPServerResponse*>& data);
void fireAfterLoad(void* pSender);
void fireRowSelected(int& pos);
void fireRowDeselected(int& pos);
private:
ListBoxCell* _pLBCell;
};
@ -138,101 +160,103 @@ protected:
// inlines
//
inline void ListBox::setHeight(int height)
{
cell<ListBoxCell>()->setHeight(height);
}
inline int ListBox::getHeight() const
{
return cell<ListBoxCell>()->getHeight();
}
inline void ListBox::setWidth(int width)
{
cell<ListBoxCell>()->setWidth(width);
}
inline int ListBox::getWidth() const
{
return cell<ListBoxCell>()->getWidth();
}
inline bool ListBox::hasSelected() const
{
return cell<ListBoxCell>()->hasSelected();
return _pLBCell->hasSelected();
}
inline ListBox::Data::const_iterator ListBox::begin() const
{
return cell<ListBoxCell>()->begin();
return _pLBCell->begin();
}
inline ListBox::Data::iterator ListBox::begin()
{
return cell<ListBoxCell>()->begin();
return _pLBCell->begin();
}
inline ListBox::Data::const_iterator ListBox::end() const
{
return cell<ListBoxCell>()->end();
return _pLBCell->end();
}
inline ListBox::Data::iterator ListBox::end()
{
return cell<ListBoxCell>()->end();
return _pLBCell->end();
}
inline void ListBox::setElements(const ListBox::Data& elems)
{
cell<ListBoxCell>()->setElements(elems);
_pLBCell->setElements(elems);
}
inline const ListBox::Data& ListBox::getElements() const
{
return cell<ListBoxCell>()->getElements();
return _pLBCell->getElements();
}
inline void ListBox::insert(const Any& elem, bool selected)
{
cell<ListBoxCell>()->insert(elem, selected);
_pLBCell->insert(elem, selected);
}
inline void ListBox::erase(const Any& elem)
{
cell<ListBoxCell>()->erase(elem);
_pLBCell->erase(elem);
}
inline void ListBox::select(const Any& elem)
{
cell<ListBoxCell>()->select(elem);
_pLBCell->select(elem);
}
inline void ListBox::deselect(const Any& elem)
{
cell<ListBoxCell>()->deselect(elem);
_pLBCell->deselect(elem);
}
inline const Any& ListBox::getSelected() const
{
return cell<ListBoxCell>()->getSelected();
return _pLBCell->getSelected();
}
inline void ListBox::selectByIndex(int idx, bool sel)
{
_pLBCell->selectByIndex(idx, sel);
}
inline void ListBox::deselectByIndex(int idx)
{
_pLBCell->deselectByIndex(idx);
}
inline void ListBox::selectAll(bool sel)
{
_pLBCell->selectAll(sel);
}
inline void ListBox::deselectAll()
{
_pLBCell->deselectAll();
}
} } // namespace Poco::WebWidgets

View File

@ -41,10 +41,15 @@
#include "Poco/WebWidgets/Cell.h"
#include "Poco/WebWidgets/Delegate.h"
#include "Poco/FIFOEvent.h"
#include <vector>
namespace Poco {
namespace Net {
class HTTPServerResponse;
}
namespace WebWidgets {
@ -57,21 +62,34 @@ public:
typedef std::vector<std::pair<Any, bool> > Data; /// An element plus its selected flag
typedef std::vector<std::string> StringData;
static const std::string EV_LOADDATA;
static const std::string EV_AFTERLOAD;
static const std::string EV_ROWSELECTED;
static const std::string ARG_SELECTED;
static const std::string ARG_ROW;
static const std::string VAL_SELECTED;
static const std::string VAL_DESELECTED;
FIFOEvent<std::pair<ListBoxCell*, Poco::Net::HTTPServerResponse*> > beforeLoad; /// thrown whenever a load is requested, internal event to which the ListBoxCellRenderer must register
Delegate afterLoad; // thrown after data was loaded
FIFOEvent<int> rowSelected; /// fires the row selected event
FIFOEvent<int> rowDeselected; /// fires the row selected event
struct WebWidgets_API RowValueChange
/// Data sent with a rowValueChanged event.
{
std::size_t row;
const Poco::Any oldValue;
const Poco::Any newValue;
RowValueChange(std::size_t row, const Poco::Any& oldValue, const Poco::Any& newValue);
};
ListBoxCell(View* pOwner);
/// Creates a ListBoxCell.
void setHeight(int height);
/// Sets the height in pixel. A negative value equals autoSize.
int getHeight() const;
/// Returns the height in pixel. A negative value equals autoSize.
void setWidth(int width);
/// Sets the width in pixel. A negative value equals autoSize.
int getWidth() const;
/// Returns the width in pixel. A negative value equals autoSize.
Data::const_iterator begin() const;
/// ConstIterator to all elements
@ -108,15 +126,31 @@ public:
void deselect(const Any& elem);
/// Deselects the element.
void selectByIndex(int idx, bool sel = true);
/// Selects the element by Index. idx values that are out of range are ignored
void deselectByIndex(int idx);
/// Deselects the element. idx values that are out of range are ignored
void selectAll(bool sel= true);
/// Selects all elements
void deselectAll();
/// Deselects all elements
bool hasSelected() const;
/// Returns true if at least one selected element exists
const Any& getSelected() const;
/// Returns the first selected element, exception if none was selected
/// Returns the first selected element, exception if none was selected.
/// To get all selected elements use getElements and iterate over the
/// returned vector
// Cell
void handleForm(const std::string& field, const std::string& value);
void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
bool serializeJSON(std::ostream& out, const std::string& name);
protected:
@ -135,37 +169,12 @@ protected:
private:
Data _data;
StringData _fmtCache;
int _height;
int _width;
};
//
// inlines
//
inline void ListBoxCell::setHeight(int height)
{
_height = height;
}
inline int ListBoxCell::getHeight() const
{
return _height;
}
inline void ListBoxCell::setWidth(int width)
{
_width = width;
}
inline int ListBoxCell::getWidth() const
{
return _width;
}
inline ListBoxCell::Data::const_iterator ListBoxCell::begin() const
{
@ -216,6 +225,18 @@ inline ListBoxCell::StringData::const_iterator ListBoxCell::endString() const
}
inline void ListBoxCell::deselectByIndex(int idx)
{
selectByIndex(idx, false);
}
inline void ListBoxCell::deselectAll()
{
selectAll(false);
}
} } // namespace Poco::WebWidgets

View File

@ -36,20 +36,21 @@
#include "Poco/WebWidgets/ListBox.h"
#include "Poco/WebWidgets/ListBoxCell.h"
#include "Poco/Delegate.h"
namespace Poco {
namespace WebWidgets {
ListBox::ListBox(const std::string& name, const std::type_info& type, Cell::Ptr ptrCell):
ListBox::ListBox(const std::string& name, const std::type_info& type, ListBoxCell::Ptr ptrCell):
Control(name, type)
{
init(ptrCell);
}
ListBox::ListBox(const std::type_info& type, Cell::Ptr ptrCell):
ListBox::ListBox(const std::type_info& type, ListBoxCell::Ptr ptrCell):
Control(type)
{
init(ptrCell);
@ -91,8 +92,12 @@ ListBox::~ListBox()
void ListBox::init()
{
ListBoxCell* pCell = new ListBoxCell(this);
setCell(pCell);
_pLBCell = new ListBoxCell(this);
_pLBCell->afterLoad = delegate(*this, &ListBox::fireAfterLoad);
_pLBCell->beforeLoad += Poco::delegate(this, &ListBox::fireBeforeLoad);
_pLBCell->rowDeselected += Poco::delegate(this, &ListBox::fireRowDeselected);
_pLBCell->rowSelected += Poco::delegate(this, &ListBox::fireRowSelected);
setCell(_pLBCell);
}
@ -100,11 +105,38 @@ void ListBox::init(Cell::Ptr ptrCell)
{
ListBoxCell::Ptr ptr = ptrCell.cast<ListBoxCell>();
poco_check_ptr (ptr);
_pLBCell = ptr;
_pLBCell->afterLoad = delegate(*this, &ListBox::fireAfterLoad);
_pLBCell->beforeLoad += Poco::delegate(this, &ListBox::fireBeforeLoad);
_pLBCell->rowDeselected += Poco::delegate(this, &ListBox::fireRowDeselected);
_pLBCell->rowSelected += Poco::delegate(this, &ListBox::fireRowSelected);
setCell(ptrCell);
}
void ListBox::fireBeforeLoad(std::pair<ListBoxCell*, Poco::Net::HTTPServerResponse*>& data)
{
beforeLoad(this, data.second);
}
void ListBox::fireAfterLoad(void* pSender)
{
ListBox* pThis = this;
afterLoad(this, pThis);
}
void ListBox::fireRowSelected(int& pos)
{
rowSelected(this, pos);
}
void ListBox::fireRowDeselected(int& pos)
{
rowDeselected(this, pos);
}
} } // namespace Poco::WebWidgets

View File

@ -35,20 +35,29 @@
#include "Poco/WebWidgets/ListBoxCell.h"
#include "Poco/WebWidgets/RequestHandler.h"
#include "Poco/DateTime.h"
#include "Poco/StringTokenizer.h"
#include "Poco/NumberParser.h"
namespace Poco {
namespace WebWidgets {
const std::string ListBoxCell::EV_LOADDATA("load");
const std::string ListBoxCell::EV_AFTERLOAD("afterLoad");
const std::string ListBoxCell::EV_ROWSELECTED("rowSel");
const std::string ListBoxCell::ARG_SELECTED("sel");
const std::string ListBoxCell::ARG_ROW("row");
const std::string ListBoxCell::VAL_SELECTED("1");
const std::string ListBoxCell::VAL_DESELECTED("0");
ListBoxCell::ListBoxCell(View* pOwner):
Cell(pOwner, typeid(ListBoxCell)),
_data(),
_fmtCache(),
_height(-1),
_width(-1)
_fmtCache()
{
}
@ -56,9 +65,7 @@ ListBoxCell::ListBoxCell(View* pOwner):
ListBoxCell::ListBoxCell(View* pOwner, const std::type_info& type):
Cell(pOwner, type),
_data(),
_fmtCache(),
_height(-1),
_width(-1)
_fmtCache()
{
}
@ -70,7 +77,25 @@ ListBoxCell::~ListBoxCell()
void ListBoxCell::handleForm(const std::string& field, const std::string& value)
{
throw Poco::NotImplementedException();
// a ListBox inside a form will just send the selected values
// may contain multiple values like "field: 1,3"
// a deselectAll() would be wrong event wise
Poco::StringTokenizer tok(value, ",", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
std::set<int> selected;
for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it)
{
int val(-1);
bool ok = Poco::NumberParser::tryParse(*it, val);
if (ok)
selected.insert(val);
}
for (int i = 0; i < _data.size(); ++i)
{
if (selected.find(i) != selected.end())
selectByIndex(i);
else
deselectByIndex(i);
}
}
@ -138,7 +163,14 @@ void ListBoxCell::select(const Any& elem)
{
Data::iterator it = find(elem);
if (it != _data.end())
it->second = true;
{
if (it->second != true)
{
it->second = true;
int idx = it - _data.begin();
rowSelected(this, idx);
}
}
}
@ -146,7 +178,14 @@ void ListBoxCell::deselect(const Any& elem)
{
Data::iterator it = find(elem);
if (it != _data.end())
it->second = false;
{
if (it->second != false)
{
it->second = false;
int idx = it - _data.begin();
rowDeselected(this, idx);
}
}
}
@ -172,18 +211,73 @@ const Any& ListBoxCell::getSelected() const
bool ListBoxCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name << ":";
if (hasSelected())
Data::const_iterator it = _data.begin();
bool written = false;
for (std::size_t i = 0; i < _data.size(); ++i)
{
const Poco::Any& sel = getSelected();
if (sel.type() == typeid(std::string) || sel.type() == typeid(Poco::DateTime))
out << ":'" << getFormatter()->format(sel) << "'";
else
out << ":" << getFormatter()->format(sel);
if (_data[i].second)
{
if (written)
out << ",";
else
written = true;
out << i;
}
}
else
if (!written)
out << "''";
return true;
}
void ListBoxCell::selectByIndex(int idx, bool sel)
{
if (idx >= 0 && idx < _data.size())
{
if (_data[idx].second != sel)
{
_data[idx].second = sel;
if (sel)
rowSelected(this, idx);
else
rowDeselected(this, idx);
}
}
}
void ListBoxCell::selectAll(bool sel)
{
Data::iterator it = _data.begin();
for (; it != _data.end(); ++it)
it->second = sel;
}
void ListBoxCell::handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response)
{
const std::string& ev = args[RequestHandler::KEY_EVID];
if (ev == EV_LOADDATA)
{
Poco::Net::HTTPServerResponse* pResp = &response;
std::pair<ListBoxCell*, Poco::Net::HTTPServerResponse*> data = std::make_pair(this, pResp);
beforeLoad(this, data);
}
else if (ev == EV_AFTERLOAD)
{
afterLoad(this);
response.send();
}
else if (ev == EV_ROWSELECTED)
{
int row = Poco::NumberParser::parse(args[ARG_ROW]);
bool sel = (args.get(ARG_SELECTED) == VAL_SELECTED);
selectByIndex(row, sel);
response.send();
}
else
response.send();
}
} } // namespace Poco::WebWidgets

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="TestSuite"
ProjectGUID="{09255B72-C314-4E57-BCF8-73698222F042}"
Keyword="Win32Proj"
@ -52,7 +52,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
@ -139,7 +138,6 @@
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool