Skip to content

Commit

Permalink
Merge pull request #43 from icza/dev
Browse files Browse the repository at this point in the history
Gowut v1.4.0 public release.
  • Loading branch information
icza committed Oct 2, 2018
2 parents 7dde321 + 8fe9e52 commit dd52803
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 37 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ language: go
go:
- 1.8
- 1.9
- "1.10"
- 1.11
- master
2 changes: 1 addition & 1 deletion _examples/showcase/showcasecore/showcasecore.go
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ func buildShowcaseWin(sess gwu.Session) {
footer.Style().SetFullWidth().SetBorderTop2(2, gwu.BrdStyleSolid, "#cccccc")
footer.Add(hiddenPan)
footer.AddHConsumer()
l = gwu.NewLabel("Copyright © 2013-2017 András Belicza. All rights reserved.")
l = gwu.NewLabel("Copyright © 2013-2018 András Belicza. All rights reserved.")
l.Style().SetFontStyle(gwu.FontStyleItalic).SetFontSize("95%")
footer.Add(l)
footer.AddHSpace(10)
Expand Down
4 changes: 2 additions & 2 deletions gwu/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ package gwu

// Gowut version information.
const (
GowutVersion = "v1.3.0" // Gowut version: "v"major.minor.maintenance[-dev]
GowutReleaseDate = "2017-09-26 CET" // Gowut release date
GowutVersion = "v1.4.0" // Gowut version: "v"major.minor.maintenance[-dev]
GowutReleaseDate = "2018-10-02 CET" // Gowut release date
GowutRelDateLayout = "2006-01-02 MST" // Gowut release date layout (for time.Parse())
)
5 changes: 5 additions & 0 deletions gwu/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const (
ETypeStateChange // State change
)

const (
// ETypeMouseDown is identical to ETypeMousedown
ETypeMouseDown = ETypeMousedown
)

// EventCategory is the event type category.
type EventCategory int

Expand Down
58 changes: 33 additions & 25 deletions gwu/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ function createXmlHttp() {
// Send event
function se(event, etype, compId, compValue) {
var xhr = createXmlHttp();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200)
procEresp(xhr);
}
xhr.open("POST", _pathEvent, true); // asynch call
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var data="";
if (etype != null)
data += "&" + _pEventType + "=" + etype;
if (compId != null)
Expand All @@ -86,11 +86,19 @@ function se(event, etype, compId, compValue) {
data += "&" + _pCompValue + "=" + compValue;
if (document.activeElement.id != null)
data += "&" + _pFocCompId + "=" + document.activeElement.id;
if (event != null) {
if (event.clientX != null) {
// Mouse data
var x = event.clientX, y = event.clientY;
// Account for the amount body is scrolled:
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
x += (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
y += (doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
data += "&" + _pMouseWX + "=" + x;
data += "&" + _pMouseWY + "=" + y;
var parent = document.getElementById(compId);
Expand All @@ -102,7 +110,7 @@ function se(event, etype, compId, compValue) {
data += "&" + _pMouseY + "=" + y;
data += "&" + _pMouseBtn + "=" + (event.button < 4 ? event.button : 1); // IE8 and below uses 4 for middle btn
}
var modKeys;
modKeys += event.altKey ? _modKeyAlt : 0;
modKeys += event.ctlrKey ? _modKeyCtlr : 0;
Expand All @@ -111,20 +119,20 @@ function se(event, etype, compId, compValue) {
data += "&" + _pModKeys + "=" + modKeys;
data += "&" + _pKeyCode + "=" + (event.which ? event.which : event.keyCode);
}
xhr.send(data);
}
function procEresp(xhr) {
var actions = xhr.responseText.split(";");
if (actions.length == 0) {
window.alert("No response received!");
return;
}
for (var i = 0; i < actions.length; i++) {
var n = actions[i].split(",");
switch (parseInt(n[0])) {
case _eraDirtyComps:
for (var j = 1; j < n.length; j++)
Expand Down Expand Up @@ -153,16 +161,16 @@ function rerenderComp(compId) {
var e = document.getElementById(compId);
if (!e) // Component removed or not visible (e.g. on inactive tab of TabPanel)
return;
var xhr = createXmlHttp();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// Remember focused comp which might be replaced here:
var focusedCompId = document.activeElement.id;
e.outerHTML = xhr.responseText;
focusComp(focusedCompId);
// Inserted JS code is not executed automatically, do it manually:
// Have to "re-get" element by compId!
var scripts = document.getElementById(compId).getElementsByTagName("script");
Expand All @@ -171,32 +179,32 @@ function rerenderComp(compId) {
}
}
}
xhr.open("POST", _pathRenderComp, false); // synch call (if async, browser specific DOM rendering errors may arise)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(_pCompId + "=" + compId);
}
// Get selected indices (of an HTML select)
function selIdxs(select) {
var selected = "";
for (var i = 0; i < select.options.length; i++)
if(select.options[i].selected)
selected += i + ",";
return selected;
}
// Get and update switch button value
function sbtnVal(event, onBtnId, offBtnId) {
var onBtn = document.getElementById(onBtnId);
var offBtn = document.getElementById(offBtnId);
if (onBtn == null)
return false;
var value = onBtn == document.elementFromPoint(event.clientX, event.clientY);
if (value) {
onBtn.className = "gwu-SwitchButton-On-Active";
Expand All @@ -205,7 +213,7 @@ function sbtnVal(event, onBtnId, offBtnId) {
onBtn.className = "gwu-SwitchButton-On-Inactive";
offBtn.className = "gwu-SwitchButton-Off-Active";
}
return value;
}
Expand Down Expand Up @@ -247,7 +255,7 @@ var timers = new Object();
function setupTimer(compId, js, timeout, repeat, active, reset) {
var timer = timers[compId];
if (timer != null) {
var changed = timer.js != js || timer.timeout != timeout || timer.repeat != repeat || timer.reset != reset;
if (!active || changed) {
Expand All @@ -262,14 +270,14 @@ function setupTimer(compId, js, timeout, repeat, active, reset) {
}
if (!active)
return;
// Create new timer
timers[compId] = timer = new Object();
timer.js = js;
timer.timeout = timeout;
timer.repeat = repeat;
timer.reset = reset;
// Start the timer
if (timer.repeat)
timer.id = setInterval(js, timeout);
Expand All @@ -281,9 +289,9 @@ function checkSession(compId) {
var e = document.getElementById(compId);
if (!e) // Component removed or not visible (e.g. on inactive tab of TabPanel)
return;
var xhr = createXmlHttp();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var timeoutSec = parseFloat(xhr.responseText);
Expand All @@ -295,7 +303,7 @@ function checkSession(compId) {
e.children[0].innerText = typeof cnvtr === 'function' ? cnvtr(timeoutSec) : convertSessTimeout(timeoutSec);
}
}
xhr.open("GET", _pathSessCheck, false); // synch call (else we can't catch connection error)
try {
xhr.send();
Expand Down
41 changes: 33 additions & 8 deletions gwu/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ const (
eraFocusComp // Focus a compnent
)

// GWU session id cookie name
const gwuSessidCookie = "gwu-sessid"
// Default GWU session id cookie name
const defaultSessIDCookieName = "gwu-sessid"

// SessionHandler interface defines a callback to get notified
// for certain events related to session life-cycles.
Expand Down Expand Up @@ -192,6 +192,13 @@ type Server interface {
// By setting your own hander, you will completely take over the app root.
SetAppRootHandler(f AppRootHandlerFunc)

// SessIDCookieName returns the cookie name used to store the Gowut
// session ID.
SessIDCookieName() string

// session ID.
SetSessIDCookieName(name string)

// Start starts the GUI server and waits for incoming connections.
//
// Sessionless window names may be specified as optional parameters
Expand Down Expand Up @@ -222,6 +229,7 @@ type serverImpl struct {
headers http.Header // Extra headers that will be added to all responses.
rootHeads []string // Additional head HTML texts of the window list page (app root)
appRootHandlerFunc AppRootHandlerFunc // App root handler function
sessIDCookieName string // Session ID cookie name

sessMux sync.RWMutex // Mutex to protect state related to session handling
}
Expand Down Expand Up @@ -252,8 +260,15 @@ func newServerImpl(appName, addr, certFile, keyFile string) *serverImpl {
addr = "localhost:3434"
}

s := &serverImpl{sessionImpl: newSessionImpl(false), appName: appName, addr: addr, sessions: make(map[string]Session),
sessCreatorNames: make(map[string]string), theme: ThemeDefault}
s := &serverImpl{
sessionImpl: newSessionImpl(false),
appName: appName,
addr: addr,
sessions: make(map[string]Session),
sessCreatorNames: make(map[string]string),
theme: ThemeDefault,
sessIDCookieName: defaultSessIDCookieName,
}

if s.appName == "" {
s.appPath = "/"
Expand Down Expand Up @@ -379,10 +394,12 @@ func (s *serverImpl) addSessCookie(sess Session, w http.ResponseWriter) {
// Secure: only send it over HTTPS
// MaxAge: to specify the max age of the cookie in seconds, else it's a session cookie and gets deleted after the browser is closed.
c := http.Cookie{
Name: gwuSessidCookie, Value: sess.ID(),
Name: s.sessIDCookieName,
Value: sess.ID(),
Path: s.appURL.EscapedPath(),
HttpOnly: true, Secure: s.secure,
MaxAge: 72 * 60 * 60, // 72 hours max age
HttpOnly: true,
Secure: s.secure,
MaxAge: 72 * 60 * 60, // 72 hours max age
}
http.SetCookie(w, &c)

Expand Down Expand Up @@ -502,6 +519,14 @@ func (s *serverImpl) SetAppRootHandler(f AppRootHandlerFunc) {
s.appRootHandlerFunc = f
}

func (s *serverImpl) SessIDCookieName() string {
return s.sessIDCookieName
}

func (s *serverImpl) SetSessIDCookieName(name string) {
s.sessIDCookieName = name
}

// serveStatic handles the static contents of GWU.
func (s *serverImpl) serveStatic(w http.ResponseWriter, r *http.Request) {
s.addHeaders(w)
Expand Down Expand Up @@ -561,7 +586,7 @@ func (s *serverImpl) serveHTTP(w http.ResponseWriter, r *http.Request) {

// Check session
var sess Session
c, err := r.Cookie(gwuSessidCookie)
c, err := r.Cookie(s.sessIDCookieName)
if err == nil {
s.sessMux.RLock()
sess = s.sessions[c.Value]
Expand Down
4 changes: 3 additions & 1 deletion gwu/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ func (c *tableImpl) Clear() {

for _, rowComps := range c.comps {
for _, c2 := range rowComps {
c2.setParent(nil)
if c2 != nil {
c2.setParent(nil)
}
}
}
c.comps = nil
Expand Down
15 changes: 15 additions & 0 deletions version-history/changes-v1.4.0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

Changes and new features in v1.4.0:
-----------------------------------

-New SessIDCookieName() and SetSessIDCookieName() methods in Server to get / set
the cookie name used to store the Gowut session ID. Useful if you plan to run
multiple Gowut servers on the same computer with the same app path (on different ports);
you can set different session ID cookie names so they won't collide (#42).

-Added ETypeMouseDown constant, identical to ETypeMousedown.

-Fixed an issue where Table.Clear() could panic if table contained nil components (#23).

-Mouse coordinates in events did not take the body's scroll amount into account, this is fixed now.
Event.Mouse() and Event.MouseWin() now return proper coordinates.

0 comments on commit dd52803

Please sign in to comment.