Could someone explain me what this code does line by line ?
how t ounderstand excactly first line with declaration ?
what does it mean: [Prop (Grid ())]?
thanks for help
gridCtrl :: Window a -> [Prop (Grid ())] -> IO (Grid ())
gridCtrl parent props
= feed2 props 0 $
initialWindow $ \id rect -> \props flags ->
do g <- gridCreate parent id rect flags
gridCreateGrid g 0 0 0
set g props
return g
In wxHaskell, controls have attached properties which can be read or changed. The stanza [Prop (Grid ())] can be understood as "a list of properties for any Grid type".
This is wxHaskell's way of dealing with the fact that the wxWidgets library, which it is built on, is object-oriented. Grid () actually means "anything in the inheritance hierarchy from which Grid derives" - i.e. Grid, ScrolledWindow, Panel, Window, EvtHandler, wxObject (you can follow this through if you start at at http://wxhaskell.sourceforge.net/doc/Graphics-UI-WXCore-WxcClassTypes.html#204)
When you look at the documentation of a Control (e.g. ListCtrl) you will find that it is reported as having a set of Attributes and Instances. Basically, you can use those which apply to the hierarchy for Grid. For example, Grid derives from ScrolledWindow, so you can use:
Attribute scrollRate
Attributes of Colored class e.g. bgcolor, color
etc.
You use these properties as follows, e.g.
g <- gridCtrl parent [color := red, bgcolor := green, scrollRate := 41]
...
set g [color := blue]
Line by line, the code reads something like the following:
Using the supplied properties (props)
and an initialWindow (which will fill in the window id and initial rect and flags), call the floowing wrapped functions in order:
gridCreate to create a new Grid instance
Using the new grid instance, set the grid inside with 0 rows, 0 columns and nothing selected.
Apply the properties (props) supplied by the caller to the grid (e.g. put data in, set styles etc.)
The part which makes the code hardest to read is the feed2 function, and that fact that the code is written in '$' style to provide the correct parameters to feed2. My slightly hand-waving explanation above should be enough, but if you want to understand the details, understand that feed2 is just composed inverted function application
feed2 x y f = f x y
then replace the '$' applications with parentheses. This doesn't look as cute, but is easier to read.
gridCtrl parent props =
feed2 props 0
(initialWindow (\id rect ->
\props flags ->
do
g <- gridCreate parent id rect flags
gridCreateGrid g 0 0 0
set g props
return g )))
Related
Suppose I have a button and a square, like this:
main = mainWidget $ do
x <- button "Change color."
y <- toggle False x
z <- mapDyn style y
elDynAttr "div" z blank
style :: Bool -> Map String String
style b | b = "style" =: "height: 10ex; width: 10ex; background-color: #f00;"
| otherwise = "style" =: "height: 10ex; width: 10ex; background-color: #900;"
The colour of the square will alternate between bright and dark red when the button is pressed.
I want to replace the button with a green rectangle in such a way that, when mouse pointer is over it, the red square is bright, otherwise dark. For bonus points, I would like the green rectangle to be a div tabindex=0 and to make sure the red square is bright when it has focus, but, once I understand the general approach, I will likely be able to figure that out by myself.
My guess is that there is some API that allows adding event handlers to el, but I did not find one so far. And maybe there is a different approch altogether, that I could not know?
The stuff you need is all found in Reflex.Dom.Widget.Basic. If you create a widget with a function that has a prime in its name, such as el', you can get a hold of an object of type El, which is a member of HasDomEvent. domEvent, the only method of this class, lets you extract an event stream corresponding to one of a selection of event names. Mixing the events together and converting them to an appropriate Dynamic is then done with some usual Reflex tooling found in Reflex.Class and Reflex.Dynamic. You do need to familiarize yourself with these interfaces, but there is a helpful quick reference.
(Make sure to use the documentation matching the version of Reflex you build against, as there are significant changes between versions.)
One way to encode your case is as follows:
main = mainWidget $ do
y <- greenBox
z <- mapDyn style y
elDynAttr "div" z blank
style :: Bool -> Map String String
style ... -- Abridged for brevity.
greenBox :: MonadWidget t m => m (Dynamic t Bool)
greenBox = do
(e, _) <- elAttr' "div" ("style" =: "height: 10ex; width: 10ex; background-color: #0c0;") blank
let
eEnter = domEvent Mouseenter e
eLeave = domEvent Mouseleave e
holdDyn False . leftmost $ [True <$ eEnter, False <$ eLeave]
What we do here is create a widget for the green box that returns a Dynamic indicating whether it is "activated". Everything else is just as it were in your initial example.
Thanks to /u/dalaing for advising me on this.
I'm trying to optimise the layout of a network I'm constructing with the following code:
gr <- read.table("data.txt", header = F, stringsAsFactors = F)
node.names <- gr[,1]
node.names <- toupper(substr(node.names, 2, nchar(node.names)))
gr <- gr[,-1]
edge.table.index <- which(gr>0.5, arr.ind=T)
d <- data.frame(first = node.names[edge.table.index[,1]], second = node.names[edge.table.index[,2]])
g <- graph.data.frame(d, directed=F)
g[from=V(g), to=V(g)] <- 0
layout.g <- layout.fruchterman.reingold(g)
plot(g, layout = layout.g, vertex.size = 5, vertex.label.cex=.7, vertex.color = "lightblue", vertex.label.family = "sans", edge.color="black", vertex.frame.color= "white")
In particular, what I'm trying to do is decrease the area on which the nodes are displayed such that the connected components are closer together. Previous versions of igraph had the option 'area' in the layout.fruchterman.reingold() function but this doesn't seem to be the case anymore. I've tried playing with various options like vertex size, vertex font size and width/height of the exported pdf file but they don't really do the trick.
Does anyone have a suggestion? Here's a link to the data file, I hope it works:
data.txt
I've been reading the source code of the Haskell Chart package as I find the charts it creates are very good. But I'm stumped on how it works.
In particular, there is a type PickFn that is used by the render function:
type PickFn a = Point -> Maybe a
data Renderable a = Renderable {
minsize :: ChartBackend RectSize,
render :: RectSize -> ChartBackend (PickFn a)
}
class ToRenderable a where
toRenderable :: a -> Renderable ()
Commentary for PickFn is "A function that maps a point in device coordinates to some value." which unfortunately doesn't mean anything to me.
My ultimate goal is to be able to follow the code to learn how it draws its charts, but I'd like to start with "what is a pick function" so that I can at least understand the types.
The pick function is a convenience to the client of the Chart library - it lets you map back from a point in the resulting image to the thing (that's the Maybe a) at that position.
For example, Graphics.Rendering.Chart.Layout.layoutToRenderable returns a Renderable (LayoutPick x y y) so that you can map back from a point in the picture back to a specific component of the layout - its legend, an axis title, the plot area, etc.
For my diagramming tool, I'd like to keep the code of the core model isolated from the GUI.
In the following example, the "state " is passed around with vDiag, which is a Tvar. This is a design decision in wx. Now, For my diagramming tool, I 'd like the core model to be "stored" in a fgl Graph, (with complex types in it), and wx will be given only a view on it; say in this example, a list of points for read access when painting, and some functions to write when clicking, dragging, etc.. . I thought first to some Monad stack, but even combining a StateT and the IO from wx does not look trivial , because the io actions are spread all over in the code of the callback (on click , on paint…etc ). It feels like having IO at the bottom of the stack does not fit well anymore.
so how to you pass a STate around, or is it not the way to go ? ( I intuition this is a classic. is this how RFP started ? )
(In the code, which paints red circle when there is a click , the list of points are passed around in a Tvar vDiag. I have tagged "--fgl" where equivalent state accessor would go. and set up a basic fgl test graph accessors to illustrate . I would like to put in a State)
(I originally tried to give it a go without FRP - reactive banana, to understand the problem, but I think I may have already hit it ;-)
module Main where
import Graphics.UI.WX hiding (empty)
import Data.Graph.Inductive
main
= start ballsFrame
ballsFrame
= do
vDiag <- varCreate []
--gDiag <- initg -- fgl
frame <- frame [text := "Demo"]
p <- panel frame []
file <- menuPane [text := "&File"]
quit <- menuQuit file [on command := close frame]
set frame [text:= "testing", menuBar := [file] ]
set p [on click := drawBins vDiag p , on paint := paintDiag vDiag ]
-- fgl pass the var around
return ()
where
drawBins d ppanel pt =
do varUpdate d (pt:)
-- addpoint f g -- fgl : insert a point
repaint ppanel
-- paint the balls
paintDiag vdiag dc view
= do balls <- varGet vdiag -- getPointsFromGraph
-- fgl : change to get the list of points
set dc [brushColor := red, brushKind := BrushSolid]
mapM_ (drawDiag dc) balls
drawDiag dc pt
= circle dc pt 10 []
-- basic fgl test graph accessors I would like to put in a State and replace vDiag
initg:: Gr Point String
initg = mkGraph [(1,pt 10 10),(2,pt 30 30)] [(1,2,"truc"), (2,1,"revtruc")]
getPointsFromGraph :: Graph gr => gr b b1 -> [b]
getPointsFromGraph g = map snd $ labNodes g
-- getPointsFromGraph initg = [Point {pointX = 10, pointY = 10},Point {pointX = 30, pointY = 30}]
addpoint :: DynGraph gr => a -> gr a b -> gr a b
addpoint p g = -- add a point p into graph p
insNode (4,p) g
I'm using the Fungen framework for Haskell and there is a function that uses BitmapFonts. The thing is, that the only BitmapFonts I can use are the ones that come with GLUT, here is the data:
data BitmapFont
= Fixed8By13
| Fixed9By15
| TimesRoman10
| TimesRoman24
| Helvetica10
| Helvetica12
| Helvetica18
These fonts are very small for my application, and I want to use another BitmapFont, not just these, or make one of these bigger. How can I do it?
Here's the source of putGameText:
putGameText :: [Text] -> IO ()
putGameText [] = return ()
putGameText ((text,font,(x,y),r,g,b):ts) = do
loadIdentity
color (Color3 r g b)
rasterPos (Vertex2 x y)
renderString font text
putGameText ts
As I understand it, FunGEn's Text type constrains font to a fixed-size BitMapFont:
type Text = (String, BitmapFont, (GLdouble, GLdouble), GLclampf, GLclampf, GLclampf)
but renderString can also take a StrokeFont, which is even more limited in font family but responds to standard OpenGL scaling/transformation/rotation.
So, a good start might be to make myPutGameText that accepts a StrokeFont-capable MyText and does a scaling transform before rendering. Here's some pseudo-code which I hope someone will correct:
type MyText = (String, StrokeFont, (GLdouble, GLdouble), GLclampf, GLclampf, GLclampf)
myPutGameText :: [MyText] -> (GLDouble,GLDouble,GLDouble) -> IO ()
myPutGameText [] _ = return ()
myPutGameText ((text,font,(x,y),r,g,b):ts) (sx,sy,sz) = do
loadIdentity
preservingMatrix $ do
scale sx sy sz
color (Color3 r g b)
rasterPos (Vertex2 x y)
renderString font text
putGameText ts
For richer font rendering, the answer is probably to integrate something like FTGL.