Skip to content

Commit 87e2887

Browse files
author
Koen Deforche
committed
Several changes:
- Shadow support in chart legend: patch from Stefan Rupert (#3502) - Fixed typo in WServerGLWidget - Suggested change in axis label rendering from Stefan Rupert (#3289) - Implemented dedicated-process deployment mode for wthttp - Made it possible to change the style of the progress bar on value change
1 parent abb5fb9 commit 87e2887

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1573
-223
lines changed

Doxyfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,8 @@ WARN_LOGFILE =
666666
# with spaces.
667667

668668
INPUT = src/Wt \
669-
doc/main
669+
doc/main \
670+
src/web
670671

671672
# This tag can be used to specify the character encoding of the source files
672673
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

INSTALL.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@ <h1>Wt Installation instructions on Unix-like systems</h1>
2626

2727
<p>
2828
The built-in web server is more convenient during development and is
29-
easier to setup.</p>
29+
easier to setup. It also allows you to use WebSockets.</p>
3030

3131
<p>
32-
The FastCGI based solution provides more flexibility for deployment of
33-
the application. The built-in web server runs all sessions in a single
34-
process, while the FastCGI based solution allows different deployment
35-
schemes including dedicated processes per sessions.</p>
32+
The FastCGI based solution can be more convenient for deployment behind another
33+
web server.</p>
3634

3735
<p>
3836
Each of these two choices correspond to a library, a

doc/main

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ namespace Wt {
233233
widgets or application in the destructors of these objects.
234234

235235
The library offers two different mechanisms to map sessions onto
236-
processes: <b>dedicated processes</b> (only with FastCGI
237-
deployment) and <b>shared processes</b>. The first mechanisms forks
236+
processes: <b>dedicated processes</b> (not with ISAPI
237+
deployment) and <b>shared processes</b>. The first mechanism forks
238238
a dedicated process for every distinct session. This provides the
239239
kernel-level isolation of different sessions, which may be useful
240240
for highly security sensitive applications. The second mechanism
@@ -554,14 +554,16 @@ appRoot=C:\Program Files\MyApplications\AppRoot
554554
<dt><strong>dedicated-process</strong></dt>
555555

556556
<dd>Every session is mapped a dedicated process, allowing maximal
557-
session isolation, but at an increased session cost. <br>
558-
This is currently only supported using the FastCGI connector.</dd>
557+
session isolation, but at an increased session cost. This is
558+
not supported by the ISAPI connector. Note: when using the
559+
<tt>wthttp</tt> adapter, this will create a listening socket
560+
on the loopback interface (<tt>127.0.0.1</tt>) for every session,
561+
with the parent process acting as a proxy.</dd>
559562

560563
<dt><strong>shared-process</strong></dt>
561564

562565
<dd>Sessions share a fixed number of processes, yielding a lower
563-
session cost. <br>
564-
This is the only option for the Wthttpd connector.</dd>
566+
session cost.</dd>
565567

566568
<dt><strong>tracking</strong></dt>
567569

src/Wt/Chart/WAxis.C

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,8 +1177,13 @@ long WAxis::getDateNumber(WDateTime dt) const
11771177

11781178
double WAxis::calcAutoNumLabels(Orientation orientation, const Segment& s) const
11791179
{
1180-
return s.renderLength
1181-
/ (orientation == Vertical ? AUTO_V_LABEL_PIXELS : AUTO_H_LABEL_PIXELS);
1180+
if (orientation == Horizontal)
1181+
return s.renderLength
1182+
/ std::max((double)AUTO_H_LABEL_PIXELS,
1183+
WLength(defaultDateTimeFormat(s).value().size(),
1184+
WLength::FontEm).toPixels());
1185+
else
1186+
return s.renderLength / AUTO_V_LABEL_PIXELS;
11821187
}
11831188

11841189
void WAxis::render(WPainter& painter,

src/Wt/Chart/WCartesianChart.C

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,6 @@ public:
650650
if (series.marker() != NoMarker) {
651651
chart_.drawMarker(series, marker_);
652652
painter_.save();
653-
painter_.setShadow(series.shadow());
654653
needRestore_ = true;
655654
} else
656655
needRestore_ = false;
@@ -680,15 +679,15 @@ public:
680679
WPen pen = WPen(series.markerPen());
681680
setPenColor(pen, xIndex, yIndex, MarkerPenColorRole);
682681

683-
painter_.setPen(pen);
684-
685682
WBrush brush = WBrush(series.markerBrush());
686683
setBrushColor(brush, xIndex, yIndex, MarkerBrushColorRole);
687-
painter_.setBrush(brush);
688-
689684
setMarkerSize(painter_, xIndex, yIndex, series.markerSize());
690685

691-
painter_.drawPath(marker_);
686+
painter_.setShadow(series.shadow());
687+
painter_.fillPath(marker_, brush);
688+
painter_.setShadow(WShadow());
689+
painter_.strokePath(marker_, pen);
690+
692691
painter_.restore();
693692
}
694693

@@ -1490,35 +1489,40 @@ void WCartesianChart::renderLegendIcon(WPainter& painter,
14901489
const WPointF& pos,
14911490
const WDataSeries& series) const
14921491
{
1492+
WShadow shadow = painter.shadow();
14931493
switch (series.type()) {
14941494
case BarSeries: {
14951495
WPainterPath path;
14961496
path.moveTo(-6, 8);
14971497
path.lineTo(-6, -8);
14981498
path.lineTo(6, -8);
14991499
path.lineTo(6, 8);
1500-
painter.setPen(series.pen());
1501-
painter.setBrush(series.brush());
15021500
painter.translate(pos.x() + 7.5, pos.y());
1503-
painter.drawPath(path);
1501+
painter.setShadow(series.shadow());
1502+
painter.fillPath(path, series.brush());
1503+
painter.setShadow(shadow);
1504+
painter.strokePath(path, series.pen());
15041505
painter.translate(-(pos.x() + 7.5), -pos.y());
15051506
break;
15061507
}
15071508
case LineSeries:
15081509
case CurveSeries: {
15091510
painter.setPen(series.pen());
15101511
double offset = (series.pen().width() == 0 ? 0.5 : 0);
1512+
painter.setShadow(series.shadow());
15111513
painter.drawLine(pos.x(), pos.y() + offset, pos.x() + 16, pos.y() + offset);
1514+
painter.setShadow(shadow);
15121515
}
15131516
// no break;
15141517
case PointSeries: {
15151518
WPainterPath path;
15161519
drawMarker(series, path);
15171520
if (!path.isEmpty()) {
15181521
painter.translate(pos.x() + 8, pos.y());
1519-
painter.setPen(series.markerPen());
1520-
painter.setBrush(series.markerBrush());
1521-
painter.drawPath(path);
1522+
painter.setShadow(series.shadow());
1523+
painter.fillPath(path, series.markerBrush());
1524+
painter.setShadow(shadow);
1525+
painter.strokePath(path, series.markerPen());
15221526
painter.translate(- (pos.x() + 8), -pos.y());
15231527
}
15241528

@@ -1536,7 +1540,7 @@ void WCartesianChart::renderLegendItem(WPainter& painter,
15361540
renderLegendIcon(painter, pos, series);
15371541

15381542
painter.setPen(fontPen);
1539-
painter.drawText(pos.x() + 17, pos.y() - 10, 100, 20,
1543+
painter.drawText(pos.x() + 23, pos.y() - 9, 100, 20,
15401544
AlignLeft | AlignMiddle,
15411545
asString(model()->headerData(series.modelColumn())));
15421546
}

src/Wt/Http/Client.C

Lines changed: 98 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ LOGGER("Http.Client");
4141
class Client::Impl : public boost::enable_shared_from_this<Client::Impl>
4242
{
4343
public:
44+
struct ChunkState {
45+
enum State { Size, Data, Complete, Error } state;
46+
std::string data;
47+
std::size_t size;
48+
int parsePos;
49+
};
50+
4451
Impl(WIOService& ioService, WServer *server, const std::string& sessionId)
4552
: ioService_(ioService),
4653
resolver_(ioService_),
@@ -312,9 +319,10 @@ private:
312319
if (boost::iequals(name, "Transfer-Encoding") &&
313320
boost::iequals(value, "chunked")) {
314321
chunkedResponse_ = true;
315-
currentChunkSize_ = 0;
316-
chunkSizeParsePos_ = 0;
317-
chunkState_ = ChunkSize;
322+
chunkState_.size = 0;
323+
chunkState_.parsePos = 0;
324+
chunkState_.state = ChunkState::Size;
325+
chunkState_.data = std::string();
318326
}
319327
}
320328
}
@@ -373,85 +381,100 @@ private:
373381
void addBodyText(const std::string& text)
374382
{
375383
if (chunkedResponse_) {
376-
std::string::const_iterator pos = text.begin();
377-
while (pos != text.end()) {
378-
switch (chunkState_) {
379-
case ChunkSize: {
380-
unsigned char ch = *(pos++);
381-
382-
switch (chunkSizeParsePos_) {
383-
case -2:
384-
if (ch != '\r') {
385-
protocolError(); return;
386-
}
387-
388-
chunkSizeParsePos_ = -1;
389-
390-
break;
391-
case -1:
392-
if (ch != '\n') {
393-
protocolError(); return;
394-
}
395-
396-
chunkSizeParsePos_ = 0;
397-
398-
break;
399-
case 0:
400-
if (ch >= '0' && ch <= '9') {
401-
currentChunkSize_ <<= 4;
402-
currentChunkSize_ |= (ch - '0');
403-
} else if (ch >= 'a' && ch <= 'f') {
404-
currentChunkSize_ <<= 4;
405-
currentChunkSize_ |= (10 + ch - 'a');
406-
} else if (ch >= 'A' && ch <= 'F') {
407-
currentChunkSize_ <<= 4;
408-
currentChunkSize_ |= (10 + ch - 'A');
409-
} else if (ch == '\r') {
410-
chunkSizeParsePos_ = 2;
411-
} else if (ch == ';') {
412-
chunkSizeParsePos_ = 1;
413-
} else {
414-
protocolError(); return;
415-
}
416-
417-
break;
418-
case 1:
419-
/* Ignoring extensions and syntax for now */
420-
if (ch == '\r')
421-
chunkSizeParsePos_ = 2;
422-
423-
break;
424-
case 2:
425-
if (ch != '\n') {
426-
protocolError(); return;
427-
}
428-
429-
if (currentChunkSize_ == 0) {
430-
complete();
431-
return;
432-
}
433-
434-
chunkState_ = ChunkData;
384+
chunkedDecode(chunkState_, text);
385+
if (chunkState_.state == ChunkState::Error) {
386+
protocolError(); return;
387+
} else if (chunkState_.state == ChunkState::Complete) {
388+
complete(); return;
389+
} else {
390+
response_.addBodyText(chunkState_.data);
391+
}
392+
} else
393+
response_.addBodyText(text);
394+
}
395+
396+
static void chunkedDecode(ChunkState& chunkState, const std::string& text)
397+
{
398+
std::string::const_iterator pos = text.begin();
399+
while (pos != text.end()) {
400+
switch (chunkState.state) {
401+
case ChunkState::Size: {
402+
unsigned char ch = *(pos++);
403+
404+
switch (chunkState.parsePos) {
405+
case -2:
406+
if (ch != '\r') {
407+
chunkState.state = ChunkState::Error; return;
435408
}
436409

410+
chunkState.parsePos = -1;
411+
437412
break;
438-
}
439-
case ChunkData:
413+
case -1:
414+
if (ch != '\n') {
415+
chunkState.state = ChunkState::Error; return;
416+
}
440417

441-
std::size_t thisChunk
442-
= std::min(std::size_t(text.end() - pos), currentChunkSize_);
443-
response_.addBodyText(std::string(pos, pos + thisChunk));
444-
currentChunkSize_ -= thisChunk;
445-
pos += thisChunk;
418+
chunkState.parsePos = 0;
419+
420+
break;
421+
case 0:
422+
if (ch >= '0' && ch <= '9') {
423+
chunkState.size <<= 4;
424+
chunkState.size |= (ch - '0');
425+
} else if (ch >= 'a' && ch <= 'f') {
426+
chunkState.size <<= 4;
427+
chunkState.size |= (10 + ch - 'a');
428+
} else if (ch >= 'A' && ch <= 'F') {
429+
chunkState.size <<= 4;
430+
chunkState.size |= (10 + ch - 'A');
431+
} else if (ch == '\r') {
432+
chunkState.parsePos = 2;
433+
} else if (ch == ';') {
434+
chunkState.parsePos = 1;
435+
} else {
436+
chunkState.state = ChunkState::Error; return;
437+
}
446438

447-
if (currentChunkSize_ == 0) {
448-
chunkSizeParsePos_ = -2;
449-
chunkState_ = ChunkSize;
439+
break;
440+
case 1:
441+
/* Ignoring extensions and syntax for now */
442+
if (ch == '\r')
443+
chunkState.parsePos = 2;
444+
445+
break;
446+
case 2:
447+
if (ch != '\n') {
448+
chunkState.state = ChunkState::Error; return;
450449
}
450+
451+
if (chunkState.size == 0) {
452+
chunkState.state = ChunkState::Complete; return;
453+
return;
454+
}
455+
456+
chunkState.state = ChunkState::Data;
451457
}
458+
459+
break;
452460
}
453-
} else
454-
response_.addBodyText(text);
461+
case ChunkState::Data: {
462+
std::size_t thisChunk
463+
= std::min(std::size_t(text.end() - pos), chunkState.size);
464+
chunkState.data = std::string(pos, pos + thisChunk);
465+
chunkState.size -= thisChunk;
466+
pos += thisChunk;
467+
468+
if (chunkState.size == 0) {
469+
chunkState.parsePos = -2;
470+
chunkState.state = ChunkState::Size;
471+
}
472+
break;
473+
}
474+
default:
475+
assert(false); // Illegal state
476+
}
477+
}
455478
}
456479

457480
void protocolError()
@@ -488,9 +511,7 @@ private:
488511
int timeout_;
489512
std::size_t maximumResponseSize_, responseSize_;
490513
bool chunkedResponse_;
491-
enum ChunkState { ChunkSize, ChunkData } chunkState_;
492-
std::size_t currentChunkSize_;
493-
int chunkSizeParsePos_;
514+
ChunkState chunkState_;
494515
boost::system::error_code err_;
495516
Message response_;
496517
Signal<boost::system::error_code, Message> done_;

src/Wt/WProgressBar

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ public:
122122
void setState(double minimum, double maximum, double value);
123123

124124
protected:
125+
/*! \brief Update the progress bar itself.
126+
*
127+
* Will be called whenever the value changes, and changes
128+
* the width of the progress bar accordingly.
129+
*
130+
* You can reimplement this method to apply certain
131+
* style changes to the progress bar according to the
132+
* value. Don't forget to call WProgressBar::updateBar
133+
* if you still want the width to change.
134+
*/
135+
virtual void updateBar(DomElement& bar);
136+
125137
virtual void updateDom(DomElement& element, bool all);
126138
virtual DomElementType domElementType() const;
127139
virtual void propagateRenderOk(bool deep);

0 commit comments

Comments
 (0)