How can I make a graphical command line in haskell/gtk2hs? - haskell

I'm trying to create my first "real program" in haskell (something that solves integrals if polynomials) but I'm completely stumped with this part of it:
I want to make something very simple a bit like GHCi:
> user input
program output
> user input
program output
> user input
program output
>
except that my program output is images (using LaTeX to turn mathematical expressions into PNGs) - so I can't do this using System.IO. I think it will be possible with gtk2hs which I've managed to install but I can't figure out how to make this input/output dialogue.
Please show me how it's done if you have the time. Thanks a lot!

We managed to come up with the following solution, thanks to ClaudiusMaximus.
module Main where
import Graphics.UI.Gtk
main = do
initGUI
----------------
win <- windowNew
onDestroy win mainQuit
vb <- vBoxNew False 3
log <- vBoxNew False 2
sc <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy sc PolicyNever PolicyAutomatic
sw <- layoutNew Nothing Nothing
en <- entryNew
----------------
scrolledWindowAddWithViewport sc log
boxPackStart vb sc PackGrow 0
boxPackStart vb en PackNatural 0
set win [ containerChild := vb ]
en `onEntryActivate` do
txt <- entryGetText en
entrySetText en ""
l <- labelNew (Just txt)
boxPackStart log l PackNatural 0
widgetShowAll log
Just ran <- scrolledWindowGetVScrollbar sc
adj <- rangeGetAdjustment ran
max <- adjustmentGetUpper adj
adjustmentSetValue adj max
----------------
widgetShowAll win
mainGUI

I think you should first implement the backend, i.e. the code for parsing a command and creating the output image. If that works, you could then implement the GUI. Basically, you need something light a text entry for input and an text and drawing widget for output. As GUI programming is (IMHO) not trivial, you should first look at some GTK/gtk2hs tutorials / introductions.

Related

cannot set position of wx.frame on openbox

i am playing with wxPython and try to set position of frame:
import wx
app = wx.App()
p = wx.Point(200, 200)
frame = wx.Frame(None, title = 'test position', pos = p)
frame.Show(True)
print('frame position: ', frame.GetPosition())
app.MainLoop()
even though print('frame position: ', frame.GetPosition()) shows the correct postion, the frame is shown in top left corner of screen.
Alternatively i tried
frame.SetPosition(p)
frame.Move(p)
without success.
my environment: ArchLinux 5.3.13, python 3.8.0, wxpython 4.0.7, openbox 3.6.1
On cinnamom the code works as expected. How to solve this on openbox?
edit 07,12,2019:
i could set postion of a dialog in openbox config ~/.config/openbox/rc.xml:
<application name="fahrplan.py"
class="Fahrplan.py"
groupname="fahrplan.py"
groupclass="Fahrplan.py"
title="Fahrplan *"
type="dialog">
<position force="no">
<x>760</x>
<y>415</y>
</position>
</application>
i got name, class etc. from obxprop. x and y are calculated to center a dialog of 400 x 250 px on screen of 1920 x 1080 px.
This static solution is not suitable for me. I want to place dynamically generated popups.
I had the same problem under Windows and played around with the style flags. With wxICONIZE sytle set active the window finally used the positioning information
The position is provided to the window manager as a "hint". It is totally up to the window manager whether it will actually honor the hint or not. Check the openbox settings or preferences and see if there is anything relevant that can be changed.

velox package point extraction failure

I am trying to work with the velox package in R 3.4.1, using the current (0.2.0) velox package version. I want to extract raster pixel values using the VeloxRaster_extract_points functionality and after failures with my own data, I ran the exact code provided on page 19 of the current reference manual. This returned the error shown (below). I have been unable to find any relevant references to this error online. Any suggestions?
Thanks
> ## Make VeloxRaster with two bands
> set.seed(0)
> mat1 <- matrix(rnorm(100), 10, 10)
> mat2 <- matrix(rnorm(100), 10, 10)
> vx <- velox(list(mat1, mat2), extent=c(0,1,0,1), res=c(0.1,0.1),crs="+proj=longlat +datum=WGS84 +no_defs")
> ## Make SpatialPoints
> library(sp)
> library(rgeos)
> coord <- cbind(runif(10), runif(10))
> spoint <- SpatialPoints(coords=coord)
> ## Extract
> vx$extract_points(sp=spoint)
Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
‘extract_points’ is not a valid field or method name for reference class “VeloxRaster”
When trying, it worked fine for my case:
library('velox')
## Make VeloxRaster with two bands
set.seed(0)
mat1 <- matrix(rnorm(100), 10, 10)
mat2 <- matrix(rnorm(100), 10, 10)
vx <- velox(list(mat1, mat2), extent=c(0,1,0,1), res=c(0.1,0.1),
crs="+proj=longlat +datum=WGS84 +no_defs")
## Make SpatialPoints
library(sp)
library(rgeos)
coord <- cbind(runif(10), runif(10))
spoint <- SpatialPoints(coords=coord)
## Extract
vx$extract_points(sp=spoint)
[,1] [,2]
[1,] 0.76359346 -0.4125199
[2,] 0.35872890 0.3178857
[3,] 0.25222345 -1.1195991
[4,] 0.00837096 2.0247614
[5,] 0.77214219 -0.5922254
[6,] 0.00837096 2.0247614
[7,] 1.10096910 0.5989751
[8,] 1.15191175 -0.9558391
[9,] 0.14377148 -1.5236149
[10,] 1.27242932 0.0465803
I think you may need to reinstall the package.

ComboBox doesn't show any of its strings

I just started using gtk2hs (gtk3 on hackage) and have run into some issues with comboBoxes.
I cannot make a simple comboBoxNewText display its strings. I have commented out everything unneeded in my application so I just have a basic framework for the actual box.
import Graphics.UI.Gtk
import Control.Monad.IO.Class
main = do
initGUI
window <- windowNew
set window [windowTitle := "Table", containerBorderWidth := 20,
windowDefaultWidth := 800, windowDefaultHeight := 600]
table <- tableNew 10 10 True
containerAdd window table
lbox <- hBoxNew False 0
rbox <- hBoxNew False 0
tableAttachDefaults table lbox 0 3 0 10
tableAttachDefaults table rbox 3 10 0 10
cb <- comboBoxNewText
comboBoxAppendText cb "test"
boxPackStart lbox cb PackGrow 10
on window deleteEvent $ liftIO mainQuit >> return False
widgetShowAll window
mainGUI
Am I missing something? gtk3 is marked as unstable iirc on hackage, could this be a bug? Or am I just doing something incorrectly?
Adding comboBoxSetActive cb 0 doesn't help either. To clarify, the actual combobox appears when I run the program, but it doesn't contain any strings/is blank.
evernote image
As Daniel Wagner commented, this does seem to be a bug in the gtk3 package on hackage. It was fixed with the commit attached to the issue linked https://github.com/gtk2hs/gtk2hs/issues/10

XMonad: start program floating based on window title

I use this truly excellent Firefox add-on: https://github.com/docwhat/itsalltext/
Hit ctrl-e to edit any textarea in Vim.
However vim starts up tiled. My browser workspaces are single-window tabbed, so a fullscreen editor is overkill. Here's what I tried to make it start as a floating window:
-- This works, but matches any vim instance, not just itsalltext instances:
-- , className =? "Gvim" --> doFloat
-- This does nothing:
, fmap (isInfixOf "itsalltext") title --> doFloat
xprop shows this for the window that is created:
WM_CLASS(STRING) = "gvim", "Gvim"
WM_ICON_NAME(STRING) = "mail.google.com.3c1b1v2w21.txt (~/.mozilla/firefox/3waevusx.default/itsalltext) - GVIM1"
_NET_WM_ICON_NAME(UTF8_STRING) = "mail.google.com.3c1b1v2w21.txt (~/.mozilla/firefox/3waevusx.default/itsalltext) - GVIM1"
WM_NAME(STRING) = "mail.google.com.3c1b1v2w21.txt (~/.mozilla/firefox/3waevusx.default/itsalltext) - GVIM1"
_NET_WM_NAME(UTF8_STRING) = "mail.google.com.3c1b1v2w21.txt (~/.mozilla/firefox/3waevusx.default/itsalltext) - GVIM1"
Bonus question: doFloat works, but I'd really like to specify how to float. For scratchpads, this works:
customFloating $ W.RationalRect (1/6) (1/6) (2/3) (2/3)
But I couldn't figure out how to use customFloating for a window that's not a scratchpad.

XMonad startup on different workspaces

I want to startup some applications in different workspaces(it is important) on xmonad start. So, I wrote following startupHook:
startupApps :: [String]
startupApps = ["konsole", "emacs", "firefox", "gvim", "konsole"]
startupSpawn :: X ()
startupSpawn = zipWithM_ id (map (spawnOn . show) [1..]) startupApps
But, it spawns all apps in first workspace. It seems to be part of more general problem -- if I start application, it get workspace not when it actually started, but when it loaded.
So, if I start firefox on WS1, then switch to WS2, firefox will spawn on WS2.
Still, what can I do about my intention?
You can use the manageHook to tell xmonad to move certain applications to certain desktops.
myManageHook = composeAll . concat $ [
[ className =? "Firefox" --> doF (shiftToWs 2) ]
, [ className =? "gvim" --> doF (shiftToWs 3) ]
-- and so on
]
The classNames might vary, though.

Resources