1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00

* improved support GTK (alpha)

git-svn-id: file:///home/shlomif/Backup/svn-dumps/PySolFC/svnsync-repos/pysolfc/PySolFC/trunk@51 efabe8c0-fbe8-4139-b769-b5e6d273206e
This commit is contained in:
skomoroh 2006-08-18 21:21:08 +00:00
parent c7df0c49ab
commit d043aabf4b
14 changed files with 644 additions and 226 deletions

View file

@ -65,7 +65,7 @@ from pysoltk import PysolMenubar
from pysoltk import PysolProgressBar from pysoltk import PysolProgressBar
from pysoltk import PysolToolbar from pysoltk import PysolToolbar
from pysoltk import PysolStatusbar, HelpStatusbar from pysoltk import PysolStatusbar, HelpStatusbar
from pysoltk import SelectCardsetByTypeDialogWithPreview from pysoltk import SelectCardsetDialogWithPreview
from pysoltk import SelectDialogTreeData from pysoltk import SelectDialogTreeData
from pysoltk import tkHTMLViewer from pysoltk import tkHTMLViewer
from pysoltk import TOOLBAR_BUTTONS from pysoltk import TOOLBAR_BUTTONS
@ -770,10 +770,6 @@ class Application:
self.intro.progress.destroy() self.intro.progress.destroy()
destruct(self.intro.progress) destruct(self.intro.progress)
self.intro.progress = None self.intro.progress = None
if TOOLKIT == 'gtk':
## FIXME
self.top.update_idletasks()
self.top.show_now()
# prepare game # prepare game
autoplay = 0 autoplay = 0
if self.nextgame.loadedgame is not None: if self.nextgame.loadedgame is not None:
@ -1155,7 +1151,7 @@ Please select a %s type %s.
def __selectCardsetDialog(self, t): def __selectCardsetDialog(self, t):
key = self.cardset.index key = self.cardset.index
d = SelectCardsetByTypeDialogWithPreview( d = SelectCardsetDialogWithPreview(
self.top, title=_("Please select a %s type %s") % (t[0], CARDSET), self.top, title=_("Please select a %s type %s") % (t[0], CARDSET),
app=self, manager=self.cardset_manager, key=key, app=self, manager=self.cardset_manager, key=key,
strings=(None, _("&OK"), _("&Cancel")), default=1) strings=(None, _("&OK"), _("&Cancel")), default=1)

View file

@ -426,6 +426,12 @@ class Game:
wm_map(self.top, maximized=self.app.opt.wm_maximized) wm_map(self.top, maximized=self.app.opt.wm_maximized)
self.top.busyUpdate() self.top.busyUpdate()
self.stopSamples() self.stopSamples()
#
if TOOLKIT == 'gtk':
## FIXME
if self.top:
self.top.update_idletasks()
self.top.show_now()
# let's go # let's go
self.moves.state = self.S_INIT self.moves.state = self.S_INIT
self.startGame() self.startGame()
@ -503,6 +509,12 @@ class Game:
self.stats.update_time = time.time() self.stats.update_time = time.time()
self.busy = old_busy self.busy = old_busy
# #
if TOOLKIT == 'gtk':
## FIXME
if self.top:
self.top.update_idletasks()
self.top.show_now()
#
self.startPlayTimer() self.startPlayTimer()
# restore a bookmarked game (e.g. after changing the cardset) # restore a bookmarked game (e.g. after changing the cardset)
@ -548,6 +560,7 @@ class Game:
# with another game from there # with another game from there
def quitGame(self, id=0, random=None, loadedgame=None, def quitGame(self, id=0, random=None, loadedgame=None,
startdemo=0, bookmark=0, holdgame=0): startdemo=0, bookmark=0, holdgame=0):
print 'quitGame'
self.updateTime() self.updateTime()
if bookmark: if bookmark:
id, random = self.id, self.random id, random = self.id, self.random

View file

@ -116,14 +116,14 @@ class _TwoImageCard(_HideableCard):
if not self.face_up: if not self.face_up:
self.__back.hide() self.__back.hide()
self.__face.show() self.__face.show()
self.tkraise(unhide) ##self.tkraise(unhide)
self.face_up = 1 self.face_up = 1
def showBack(self, unhide=1): def showBack(self, unhide=1):
if self.face_up: if self.face_up:
self.__face.hide() self.__face.hide()
self.__back.show() self.__back.show()
self.tkraise(unhide) ##self.tkraise(unhide)
self.face_up = 0 self.face_up = 0
def updateCardBackground(self, image): def updateCardBackground(self, image):
@ -133,5 +133,5 @@ class _TwoImageCard(_HideableCard):
# choose the implementation # choose the implementation
Card = _TwoImageCard Card = _TwoImageCard
Card = _OneImageCard #Card = _OneImageCard # FIXME: this implementation lost any cards (bug?)

View file

@ -45,7 +45,6 @@ from pysollib.settings import PACKAGE
from tkutil import setTransient from tkutil import setTransient
from tkutil import color_tk2gtk, color_gtk2tk from tkutil import color_tk2gtk, color_gtk2tk
from selectcardset import SelectCardsetDialogWithPreview from selectcardset import SelectCardsetDialogWithPreview
from selectcardset import SelectCardsetByTypeDialogWithPreview
from selecttile import SelectTileDialogWithPreview from selecttile import SelectTileDialogWithPreview
from selectgame import SelectGameDialogWithPreview from selectgame import SelectGameDialogWithPreview
@ -87,57 +86,144 @@ class PysolMenubar(PysolMenubarActions):
def createMenubar(self): def createMenubar(self):
entries = ( entries = (
('newgame', gtk.STOCK_NEW, ltk2gtk('&New game'), 'N', ltk2gtk('New game'), self.mNewGame),
('open', gtk.STOCK_OPEN, ltk2gtk('&Open...'), '<control>O', ltk2gtk('Open a\nsaved game'), self.mOpen),
('restart', gtk.STOCK_REFRESH, ltk2gtk('&Restart'), '<control>G', ltk2gtk('Restart the\ncurrent game'), self.mRestart),
('save', gtk.STOCK_SAVE, ltk2gtk('&Save'), '<control>S', ltk2gtk('Save game'), self.mSave),
('undo', gtk.STOCK_UNDO, ltk2gtk('&Undo'), 'Z', ltk2gtk('Undo'), self.mUndo),
('redo', gtk.STOCK_REDO, ltk2gtk('&Redo'), 'R', ltk2gtk('Redo'), self.mRedo),
('autodrop',gtk.STOCK_JUMP_TO, ltk2gtk('&Auto drop'), 'A', ltk2gtk('Auto drop'), self.mDrop),
('stats', gtk.STOCK_HOME, ltk2gtk('Stats'), None, ltk2gtk('Statistics'), self.mStatus),
('rules', gtk.STOCK_HELP, ltk2gtk('Rules'), 'F1', ltk2gtk('Rules'), self.mHelpRules),
('quit', gtk.STOCK_QUIT, ltk2gtk('&Quit'), '<control>Q', ltk2gtk('Quit PySol'), self.mQuit),
### toolbar
('newgame', gtk.STOCK_NEW,
ltk2gtk('&New game'), 'N',
ltk2gtk('New game'),
self.mNewGame),
('open', gtk.STOCK_OPEN,
ltk2gtk('&Open...'), '<control>O',
ltk2gtk('Open a\nsaved game'),
self.mOpen),
('restart', gtk.STOCK_REFRESH,
ltk2gtk('&Restart'), '<control>G',
ltk2gtk('Restart the\ncurrent game'),
self.mRestart),
('save', gtk.STOCK_SAVE,
ltk2gtk('&Save'), '<control>S',
ltk2gtk('Save game'),
self.mSave),
('undo', gtk.STOCK_UNDO,
ltk2gtk('&Undo'), 'Z',
ltk2gtk('Undo'),
self.mUndo),
('redo', gtk.STOCK_REDO,
ltk2gtk('&Redo'), 'R',
ltk2gtk('Redo'),
self.mRedo),
('autodrop', gtk.STOCK_JUMP_TO,
ltk2gtk('&Auto drop'), 'A',
ltk2gtk('Auto drop'),
self.mDrop),
('stats', gtk.STOCK_INDEX,
ltk2gtk('Stats'), None,
ltk2gtk('Statistics'),
self.mStatus),
('rules', gtk.STOCK_HELP,
ltk2gtk('Rules'), 'F1',
ltk2gtk('Rules'),
self.mHelpRules),
('quit', gtk.STOCK_QUIT,
ltk2gtk('&Quit'), '<control>Q',
ltk2gtk('Quit PySol'),
self.mQuit),
### menus
('file', None, ltk2gtk('&File')), ('file', None, ltk2gtk('&File')),
('selectgame', None, ltk2gtk('Select &game')), ('selectgame', None, ltk2gtk('Select &game')),
('edit', None, ltk2gtk('&Edit')), ('edit', None, ltk2gtk('&Edit')),
('game', None, ltk2gtk('&Game')), ('game', None, ltk2gtk('&Game')),
('assist', None, ltk2gtk('&Assist')), ('assist', None, ltk2gtk('&Assist')),
('options', None, ltk2gtk('&Options')), ('options', None, ltk2gtk('&Options')),
('assistlevel', None, ltk2gtk("Assist &level")),
("automaticplay", None, ltk2gtk("&Automatic play")), ("automaticplay", None, ltk2gtk("&Automatic play")),
('animations', None, ltk2gtk('A&nimations')), ('animations', None, ltk2gtk('A&nimations')),
('help', None, ltk2gtk('&Help')), ('help', None, ltk2gtk('&Help')),
('playablepreview', None, ltk2gtk('Playable pre&view...'), 'V', None, self.mSelectGameDialogWithPreview), ### menuitems
('selectgamebynumber', None, ltk2gtk('Select game by nu&mber...'), None, None, self.mSelectGameById), ('playablepreview', None,
('saveas', None, ltk2gtk('Save &as...'), None, None, self.m), ltk2gtk('Playable pre&view...'), 'V',
('redoall', None, ltk2gtk('Redo &all'), None, None, self.mRedoAll), None, self.mSelectGameDialogWithPreview),
('dealcards', None, ltk2gtk('&Deal cards'), 'D', None, self.mDeal), ('selectgamebynumber', None,
('status', None, ltk2gtk('S&tatus...'), 'T', None, self.mStatus), ltk2gtk('Select game by nu&mber...'), None,
('hint', None, ltk2gtk('&Hint'), 'H', None, self.mHint), None, self.mSelectGameById),
('highlightpiles', None, ltk2gtk('Highlight p&iles'), None, None, self.mHighlightPiles), ('saveas', None,
('demo', None,ltk2gtk('&Demo'), '<control>D',None,self.mDemo), ltk2gtk('Save &as...'), None,
('demoallgames', None,ltk2gtk('Demo (&all games)'), None,None,self.mMixedDemo), None, self.m),
('playeroptions',None,ltk2gtk('&Player options...'),None,None,self.mOptPlayerOptions), ('redoall', None,
('tabletile', None,ltk2gtk('Table t&ile...'), None,None,self.mOptTableTile), ltk2gtk('Redo &all'), None,
('contents', None,ltk2gtk('&Contents'),'<control>F1',None,self.mHelp), None, self.mRedoAll),
('aboutpysol', None,ltk2gtk('&About ')+PACKAGE+'...', None,None,self.mHelpAbout), ('dealcards', None,
) ltk2gtk('&Deal cards'), 'D',
None, self.mDeal),
('status', None,
ltk2gtk('S&tatus...'), 'T',
None, self.mStatus),
('hint', None,
ltk2gtk('&Hint'), 'H',
None, self.mHint),
('highlightpiles', None,
ltk2gtk('Highlight p&iles'), None,
None, self.mHighlightPiles),
('demo', None,
ltk2gtk('&Demo'), '<control>D',
None,self.mDemo),
('demoallgames', None,
ltk2gtk('Demo (&all games)'), None,
None,self.mMixedDemo),
('playeroptions', None,
ltk2gtk('&Player options...'), None,
None,self.mOptPlayerOptions),
('tabletile', None,
ltk2gtk('Table t&ile...'), None,
None,self.mOptTableTile),
('cardset', None,
ltk2gtk('Cards&et...'), '<control>E',
None, self.mSelectCardsetDialog),
('contents', None,
ltk2gtk('&Contents'), '<control>F1',
None, self.mHelp),
('aboutpysol', None,
ltk2gtk('&About ')+PACKAGE+'...',
None,None,self.mHelpAbout),
('updateall', None,
'Redraw Game', '<control>L',
None,
self.updateAll),
)
# #
toggle_entries = ( toggle_entries = [
('pause', gtk.STOCK_STOP, ltk2gtk('&Pause'), 'P', ltk2gtk('Pause game'), self.mPause), ('pause', # name
('optautodrop', None, ltk2gtk('A&uto drop'), None, None, self.mOptAutoDrop), gtk.STOCK_STOP, ltk2gtk('&Pause'), # stock, label
('autofaceup', None, ltk2gtk('Auto &face up'), None, None, self.mOptAutoFaceUp), 'P', ltk2gtk('Pause game'), # accelerator, tooltip
("autodeal", None, ltk2gtk("Auto &deal"), None, None, self.mOptAutoDeal), self.mPause, # callback
("quickplay", None, ltk2gtk('&Quick play'), None, None, self.mOptQuickPlay), False, # initial value
), ]
('highlightmatchingcards', None, ltk2gtk('Highlight &matching cards'), None, None, self.mOptEnableHighlightCards), for label, name, opt_name in (
('cardshadow', None, ltk2gtk('Card shado&w'), None, None, self.mOptShadow), ('A&uto drop', 'optautodrop', 'autodrop'),
('shadelegalmoves', None, ltk2gtk('Shade &legal moves'), None, None, self.mOptShade), ('Auto &face up', '', 'autofaceup'),
('Auto &deal', '', 'autodeal'),
) ('&Quick play', '', 'quickplay'),
('Enable &undo', '', 'undo'),
('Enable &bookmarks' , '', 'bookmarks'),
('Enable &hint', '', 'hint'),
('Enable highlight p&iles', '', 'highlight_piles'),
('Enable highlight &cards', '', 'highlight_cards'),
('Enable highlight same &rank', '', 'highlight_samerank'),
('Highlight &no matching', '', 'highlight_not_matching'),
('Card shado&w', '', 'shadow'),
('Shade &legal moves', '', 'shade'),
):
if not name:
name = re.sub(r"[^0-9a-zA-Z]", "", label).lower()
toggle_entries.append(
(name,
None, ltk2gtk(label),
None, None,
lambda w, opt_name=opt_name: self.mOptToggle(w, opt_name),
getattr(self.app.opt, opt_name)))
# #
animations_entries = ( animations_entries = (
@ -170,6 +256,8 @@ class PysolMenubar(PysolMenubarActions):
<menuitem action='redoall'/> <menuitem action='redoall'/>
<separator/> <separator/>
<menuitem action='restart'/> <menuitem action='restart'/>
<separator/>
<menuitem action='updateall'/>
</menu> </menu>
<menu action='game'> <menu action='game'>
@ -196,9 +284,18 @@ class PysolMenubar(PysolMenubarActions):
<separator/> <separator/>
<menuitem action='quickplay'/> <menuitem action='quickplay'/>
</menu> </menu>
<menuitem action='highlightmatchingcards'/> <menu action='assistlevel'>
<menuitem action='enableundo'/>
<menuitem action='enablebookmarks'/>
<menuitem action='enablehint'/>
<menuitem action='enablehighlightpiles'/>
<menuitem action='enablehighlightcards'/>
<menuitem action='enablehighlightsamerank'/>
<menuitem action='highlightnomatching'/>
</menu>
<separator/> <separator/>
<menuitem action='tabletile'/> <menuitem action='tabletile'/>
<menuitem action='cardset'/>
<menu action='animations'> <menu action='animations'>
<menuitem action='animationnone'/> <menuitem action='animationnone'/>
<menuitem action='animationtimer'/> <menuitem action='animationtimer'/>
@ -395,8 +492,6 @@ class PysolMenubar(PysolMenubarActions):
self.updateMenus() self.updateMenus()
def mOptCardset(self, *args):
pass
def mOptTableTile(self, *args): def mOptTableTile(self, *args):
if self._cancelDrag(break_pause=False): return if self._cancelDrag(break_pause=False): return
@ -469,3 +564,29 @@ class PysolMenubar(PysolMenubarActions):
self.game.quitGame(d.gameid, random=d.random) self.game.quitGame(d.gameid, random=d.random)
def mSelectCardsetDialog(self, *event):
if self._cancelDrag(break_pause=False): return
key = self.app.nextgame.cardset.index
d = SelectCardsetDialogWithPreview(self.top, title=_("Select cardset"),
app=self.app, manager=self.app.cardset_manager, key=key)
cs = self.app.cardset_manager.get(d.key)
if cs is None or d.key == self.app.cardset.index:
return
if d.status == 0 and d.button in (0, 1) and d.key >= 0:
self.app.nextgame.cardset = cs
if d.button == 0:
self._cancelDrag()
self.game.endGame(bookmark=1)
self.game.quitGame(bookmark=1)
self.app.opt.games_geometry = {} # clear saved games geometry
def mOptToggle(self, w, opt):
##print 'mOptToggle:', opt, w.get_active()
if self._cancelDrag(break_pause=False): return
self.app.opt.__dict__[opt] = w.get_active()
def updateAll(self, *event):
self.app.canvas.updateAll()

View file

@ -65,7 +65,6 @@ class PlayerOptionsDialog(MfxDialog):
completion = gtk.EntryCompletion() completion = gtk.EntryCompletion()
self.player_entry.set_completion(completion) self.player_entry.set_completion(completion)
model = gtk.ListStore(gobject.TYPE_STRING) model = gtk.ListStore(gobject.TYPE_STRING)
print '>>', app.getAllUserNames()
for name in app.getAllUserNames(): for name in app.getAllUserNames():
iter = model.append() iter = model.append()
model.set(iter, 0, name) model.set(iter, 0, name)

View file

@ -0,0 +1,125 @@
##---------------------------------------------------------------------------##
##
## PySol -- a Python Solitaire game
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; see the file COPYING.
## If not, write to the Free Software Foundation, Inc.,
## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
##
##---------------------------------------------------------------------------##
# imports
import os, re, sys, types
import gtk, gobject
# PySol imports
# Toolkit imports
# /***********************************************************************
# //
# ************************************************************************/
class PysolTreeView:
_expanded_rows = []
_selected_row = None
_vadjustment_position = None
def __init__(self, parent, store, **kw):
#
sw = gtk.ScrolledWindow()
self.scrolledwindow = sw
sw.show()
self.sw_vadjustment = sw.get_vadjustment()
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
#
treeview = gtk.TreeView(store)
self.treeview = treeview
treeview.show()
sw.add(treeview)
treeview.set_rules_hint(True)
treeview.set_headers_visible(False)
renderer = gtk.CellRendererText()
renderer.set_property('xalign', 0.0)
column = gtk.TreeViewColumn('Column Name', renderer, text=0)
column.set_clickable(True)
treeview.append_column(column)
selection = treeview.get_selection()
selection.connect('changed', parent.showSelected)
treeview.connect('unrealize', self._unrealizeEvent)
self._restoreSettings()
def _unrealizeEvent(self, w):
self._saveSettings()
def _saveSettings(self):
self._saveExpandedRows()
selection = self.treeview.get_selection()
model, path = selection.get_selected_rows()
if path:
PysolTreeView._selected_row = path[0]
PysolTreeView._vadjustment_position = self.sw_vadjustment.get_value()
def _restoreSettings(self):
self._loadExpandedRows()
if self._selected_row:
selection = self.treeview.get_selection()
##selection.select_path(self._selected_row)
##selection.unselect_all()
gtk.idle_add(selection.select_path, self._selected_row)
if self._vadjustment_position is not None:
##self.sw_vadjustment.set_value(self._vadjustment_position)
gtk.idle_add(self.sw_vadjustment.set_value,
self._vadjustment_position)
def _saveExpandedRows(self):
treeview = self.treeview
PysolTreeView._expanded_rows = []
treeview.map_expanded_rows(
lambda tv, path, self=self:
PysolTreeView._expanded_rows.append(path))
def _loadExpandedRows(self):
for path in self._expanded_rows:
self.treeview.expand_to_path(path)
def getSelected(self):
selection = self.treeview.get_selection()
model, path = selection.get_selected_rows()
if not path:
return None
iter = model.get_iter(path[0])
index = model.get_value(iter, 1)
return index
def unselectAll(self):
selection = self.treeview.get_selection()
selection.unselect_all()

View file

@ -32,10 +32,17 @@
# imports # imports
import os, re, sys, types import os, re, sys, types
from gtk import * import gtk, gobject
# PySol imports
from pysollib.resource import CSI
from pysollib.mfxutil import kwdefault
# Toolkit imports # Toolkit imports
from tkwidget import MfxDialog from tkwidget import MfxDialog
from pysoltree import PysolTreeView
from tkcanvas import MfxCanvas, MfxCanvasImage
from tkutil import loadImage
# /*********************************************************************** # /***********************************************************************
@ -43,8 +50,221 @@ from tkwidget import MfxDialog
# ************************************************************************/ # ************************************************************************/
class SelectCardsetDialogWithPreview(MfxDialog): class SelectCardsetDialogWithPreview(MfxDialog):
_cardset_store = None
def __init__(self, parent, title, app, manager, key=None, **kw):
kw = self.initKw(kw)
MfxDialog.__init__(self, parent, title, **kw)
#
top_box, bottom_box = self.createHBox()
#
if key is None:
key = manager.getSelected()
self.app = app
self.manager = manager
self.key = key
self.preview_key = -1
self.all_keys = []
if self._cardset_store is None:
self._createStore()
#padx, pady = kw.padx, kw.pady
padx, pady = 5, 5
# left
# paned
hpaned = gtk.HPaned()
self.hpaned = hpaned
hpaned.show()
top_box.pack_start(hpaned, expand=True, fill=True)
# tree
treeview = PysolTreeView(self, self._cardset_store)
self.treeview = treeview
hpaned.pack1(treeview.scrolledwindow, True, True)
##treeview.treeview.expand_all()
# right
sw = gtk.ScrolledWindow()
sw.show()
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
hpaned.pack2(sw, True, True)
##self.scrolledwindow = sw
#
self.preview = MfxCanvas(self)
self.preview.show()
sw.add(self.preview)
#hpaned.pack2(self.preview, True, True)
self.preview.setTile(app, app.tabletile_index, force=True)
#
hpaned.set_position(240)
self.createButtons(bottom_box, kw)
##~self.updatePreview(key)
self.show_all()
gtk.main()
def _selectCardset(self, all_cardsets, selecter):
if selecter is None:
return [(cs.index, cs.name) for cs in all_cardsets]
return [(cs.index, cs.name) for cs in all_cardsets if selecter(cs)]
def _addCardsets(self, store, root_iter, root_label, cardsets):
iter = store.append(root_iter)
store.set(iter, 0, root_label, 1, -1)
for index, name in cardsets:
child_iter = store.append(iter)
##~ name = gettext(name)
store.set(child_iter, 0, name, 1, index)
def _addCardsetsByType(self, store, root_label, all_cardsets,
cardset_types, selecter_type, registered):
manager = self.manager
root_iter = store.append(None)
store.set(root_iter, 0, root_label, 1, -1)
items = cardset_types.items()
items.sort(lambda a, b: cmp(a[1], b[1]))
added = False
for key, label in items:
if not getattr(manager, registered).has_key(key):
continue
cardsets = []
for cs in all_cardsets:
si = getattr(cs.si, selecter_type)
if type(si) is int: # type
if key == si:
cardsets.append((cs.index, cs.name))
else: # style, nationality, date
if key in si:
cardsets.append((cs.index, cs.name))
if cardsets:
added = True
self._addCardsets(store, root_iter, label, cardsets)
if added:
selecter = lambda cs, selecter_type=selecter_type: \
not getattr(cs.si, selecter_type)
cs = self._selectCardset(all_cardsets, selecter)
if cs:
self._addCardsets(store, root_iter, _('Uncategorized'), cs)
else:
iter = store.append(root_iter)
store.set(iter, 0, _('(no cardsets)'), 1, -1)
def _createStore(self):
store = gtk.TreeStore(gobject.TYPE_STRING,
gobject.TYPE_INT)
manager = self.manager
all_cardsets = manager.getAllSortedByName()
all_cardsets = filter(lambda obj: not obj.error, all_cardsets)
cs = self._selectCardset(all_cardsets, None)
self._addCardsets(store, None, 'All cadsets', cs)
root_iter = store.append(None)
store.set(root_iter, 0, _('by Size'), 1, -1)
for label, selecter in (
(_("Tiny cardsets"), lambda cs: cs.si.size == CSI.SIZE_TINY),
(_("Small cardsets"), lambda cs: cs.si.size == CSI.SIZE_SMALL),
(_("Medium cardsets"), lambda cs: cs.si.size == CSI.SIZE_MEDIUM),
(_("Large cardsets"), lambda cs: cs.si.size == CSI.SIZE_LARGE),
(_("XLarge cardsets"), lambda cs: cs.si.size == CSI.SIZE_XLARGE),):
cs = self._selectCardset(all_cardsets, selecter)
if cs:
self._addCardsets(store, root_iter, label, cs)
self._addCardsetsByType(store, _('by Type'), all_cardsets,
CSI.TYPE, 'type', 'registered_types')
self._addCardsetsByType(store, _('by Style'), all_cardsets,
CSI.STYLE, 'styles', 'registered_styles')
self._addCardsetsByType(store, _('by Nationality'), all_cardsets,
CSI.NATIONALITY, 'nationalities',
'registered_nationalities')
self._addCardsetsByType(store, _('by Date'), all_cardsets,
CSI.DATE, 'dates', 'registered_dates')
self._cardset_store = store
def getSelected(self):
index = self.treeview.getSelected()
if index < 0:
return None
return index
def showSelected(self, w):
key = self.getSelected()
if not key is None:
self.updatePreview(key)
pass pass
class SelectCardsetByTypeDialogWithPreview(SelectCardsetDialogWithPreview):
def updatePreview(self, key):
if key == self.preview_key:
return
canvas = self.preview
canvas.deleteAllItems()
self.preview_images = []
cs = self.manager.get(key)
if not cs:
self.preview_key = -1
return
names, columns = cs.getPreviewCardNames()
try:
#???names, columns = cs.getPreviewCardNames()
for n in names:
f = os.path.join(cs.dir, n + cs.ext)
self.preview_images.append(loadImage(file=f))
except:
self.preview_key = -1
self.preview_images = []
return
i, x, y, sx, sy, dx, dy = 0, 10, 10, 0, 0, cs.CARDW + 10, cs.CARDH + 10
for image in self.preview_images:
MfxCanvasImage(canvas, x, y, anchor="nw", image=image)
sx, sy = max(x, sx), max(y, sy)
i = i + 1
if i % columns == 0:
x, y = 10, y + dy
else:
x = x + dx
canvas.config(width=sx+dx, height=sy+dy)
canvas.set_scroll_region(0, 0, sx+dx, sy+dy)
self.preview_key = key
def initKw(self, kw):
kwdefault(kw,
strings=(_("&Load"), _("&Cancel"), _("&Info..."),),
default=1,
resizable=1,
padx=10, pady=10,
width=600, height=400,
)
return MfxDialog.initKw(self, kw)
def createInfo(self):
pass pass
def done(self, button):
b = button.get_data('user_data')
if b == 2:
self.createInfo()
return
if b == 0:
self.key = self.getSelected()
if not self.key:
self.key = self.preview_key
self.status = 0
self.button = b
self.hide()
self.quit()

View file

@ -52,6 +52,7 @@ from pysollib.resource import CSI
from tkutil import unbind_destroy from tkutil import unbind_destroy
from tkwidget import MfxDialog from tkwidget import MfxDialog
from tkcanvas import MfxCanvas, MfxCanvasText from tkcanvas import MfxCanvas, MfxCanvasText
from pysoltree import PysolTreeView
gettext = _ gettext = _
@ -89,25 +90,8 @@ class SelectGameDialogWithPreview(MfxDialog):
hpaned.show() hpaned.show()
top_box.pack_start(hpaned, expand=True, fill=True) top_box.pack_start(hpaned, expand=True, fill=True)
# left # left
sw = gtk.ScrolledWindow() self.treeview = PysolTreeView(self, self.game_store)
sw.show() hpaned.pack1(self.treeview.scrolledwindow, True, True)
self.sw_vadjustment = sw.get_vadjustment()
hpaned.pack1(sw, True, True)
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
# tree
treeview = gtk.TreeView(self.game_store)
self.treeview = treeview
treeview.show()
sw.add(treeview)
treeview.set_rules_hint(True)
treeview.set_headers_visible(False)
renderer = gtk.CellRendererText()
renderer.set_property('xalign', 0.0)
column = gtk.TreeViewColumn('Games', renderer, text=0)
column.set_clickable(True)
treeview.append_column(column)
selection = treeview.get_selection()
selection.connect('changed', self.showSelected)
# right # right
table = gtk.Table(2, 2, False) table = gtk.Table(2, 2, False)
table.show() table.show()
@ -228,8 +212,6 @@ class SelectGameDialogWithPreview(MfxDialog):
name = gettext(name) name = gettext(name)
store.set(child_iter, 0, name, 1, id) store.set(child_iter, 0, name, 1, id)
#def _addNode(self, store, root_iter, root_label, games):
def _selectGames(self, all_games, selecter): def _selectGames(self, all_games, selecter):
# return list of tuples (gameid, gamename) # return list of tuples (gameid, gamename)
@ -350,9 +332,7 @@ class SelectGameDialogWithPreview(MfxDialog):
kwdefault(kw, kwdefault(kw,
strings=(_("&Select"), _("&Rules"), _("&Cancel"),), strings=(_("&Select"), _("&Rules"), _("&Cancel"),),
default=0, default=0,
##padx=10, pady=10,
width=600, height=400, width=600, height=400,
##~ buttonpadx=10, buttonpady=5,
) )
return MfxDialog.initKw(self, kw) return MfxDialog.initKw(self, kw)
@ -365,49 +345,25 @@ class SelectGameDialogWithPreview(MfxDialog):
def _saveSettings(self): def _saveSettings(self):
SelectGameDialogWithPreview._geometry = self.get_size() SelectGameDialogWithPreview._geometry = self.get_size()
self._saveExpandedRows()
SelectGameDialogWithPreview._paned_position = self.hpaned.get_position() SelectGameDialogWithPreview._paned_position = self.hpaned.get_position()
selection = self.treeview.get_selection()
model, path = selection.get_selected_rows()
if path:
print 'save selected:', path
SelectGameDialogWithPreview._selected_row = path[0]
SelectGameDialogWithPreview._vadjustment_position = self.sw_vadjustment.get_value()
def _restoreSettings(self): def _restoreSettings(self):
if self._geometry: if self._geometry:
self.resize(self._geometry[0], self._geometry[1]) self.resize(self._geometry[0], self._geometry[1])
self._loadExpandedRows()
self.hpaned.set_position(self._paned_position) self.hpaned.set_position(self._paned_position)
if self._selected_row:
selection = self.treeview.get_selection()
##selection.select_path(self._selected_row)
##selection.unselect_all()
gtk.idle_add(selection.select_path, self._selected_row)
if self._vadjustment_position is not None:
##self.sw_vadjustment.set_value(self._vadjustment_position)
gtk.idle_add(self.sw_vadjustment.set_value,
self._vadjustment_position)
def _getSelected(self): def getSelected(self):
selection = self.treeview.get_selection() index = self.treeview.getSelected()
model, path = selection.get_selected_rows()
if not path:
return None
iter = model.get_iter(path[0])
index = model.get_value(iter, 1)
if index < 0: if index < 0:
return None return None
return index return index
def showSelected(self, w): def showSelected(self, w):
id = self._getSelected() id = self.getSelected()
if id: if id:
self.updatePreview(id) self.updatePreview(id)
##self.updateInfo(id)
def deletePreview(self, destroy=0): def deletePreview(self, destroy=0):
@ -568,28 +524,16 @@ class SelectGameDialogWithPreview(MfxDialog):
text_label.set_text(str(t)) text_label.set_text(str(t))
#self.info_labels[n].config(text=t) #self.info_labels[n].config(text=t)
def _saveExpandedRows(self):
treeview = self.treeview
SelectGameDialogWithPreview._expanded_rows = []
treeview.map_expanded_rows(
lambda tv, path, self=self:
SelectGameDialogWithPreview._expanded_rows.append(path))
print self._expanded_rows
def _loadExpandedRows(self):
for path in self._expanded_rows:
self.treeview.expand_to_path(path)
def done(self, button): def done(self, button):
button = button.get_data("user_data") button = button.get_data("user_data")
print 'done', button print 'done', button
if button == 0: # Ok or double click if button == 0: # Ok or double click
id = self._getSelected() id = self.getSelected()
if id: if id:
self.gameid = id self.gameid = id
##~ self.tree.n_expansions = 1 # save xyview in any case ##~ self.tree.n_expansions = 1 # save xyview in any case
if button == 1: # Rules if button == 1: # Rules
id = self._getSelected() id = self.getSelected()
if id: if id:
doc = self.app.getGameRulesFilename(id) doc = self.app.getGameRulesFilename(id)
if not doc: if not doc:

View file

@ -26,16 +26,17 @@
import gobject, gtk import gobject, gtk
from gtk import gdk from gtk import gdk
## # PySol imports # PySol imports
## from pysollib.mfxutil import destruct, Struct, KwStruct ## from pysollib.mfxutil import destruct, Struct, KwStruct
from pysollib.resource import CSI from pysollib.resource import CSI
from pysollib.mfxutil import kwdefault, KwStruct from pysollib.mfxutil import kwdefault
# Toolkit imports # Toolkit imports
## from tkutil import loadImage ## from tkutil import loadImage
from tkwidget import MfxDialog from tkwidget import MfxDialog
from tkcanvas import MfxCanvas from tkcanvas import MfxCanvas
from tkutil import setTransient from tkutil import setTransient
from pysoltree import PysolTreeView
class SelectTileDialogWithPreview(MfxDialog): class SelectTileDialogWithPreview(MfxDialog):
@ -54,38 +55,22 @@ class SelectTileDialogWithPreview(MfxDialog):
self.preview_key = -1 self.preview_key = -1
self.all_keys = [] self.all_keys = []
self.table_color = app.opt.table_color self.table_color = app.opt.table_color
# paned
sw = gtk.ScrolledWindow() hpaned = gtk.HPaned()
sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.hpaned = hpaned
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) hpaned.show()
top_box.pack_start(sw) top_box.pack_start(hpaned, expand=True, fill=True)
# #
model = self._create_tree_model(manager, key) model = self._createStore(manager, key)
treeview = gtk.TreeView(model) treeview = PysolTreeView(self, model)
treeview.set_rules_hint(True)
treeview.set_headers_visible(False)
renderer = gtk.CellRendererText()
renderer.set_property('xalign', 0.0)
column = gtk.TreeViewColumn('Tiles', renderer, text=0)
column.set_clickable(True)
treeview.append_column(column)
sw.add(treeview)
treeview.expand_all()
selection = treeview.get_selection()
selection.connect('changed', self.treeview_show_selected)
treeview.connect('row-activated', self.row_activated)
self.treeview = treeview self.treeview = treeview
hpaned.pack1(treeview.scrolledwindow, True, True)
treeview.treeview.expand_all()
# #
self.preview = MfxCanvas(top_box) # width=w2 self.preview = MfxCanvas(top_box) # width=w2
top_box.pack_end(self.preview) hpaned.pack2(self.preview, True, True)
self.preview.show() self.preview.show()
hpaned.set_position(240)
self.createButtons(bottom_box, kw) self.createButtons(bottom_box, kw)
@ -95,28 +80,24 @@ class SelectTileDialogWithPreview(MfxDialog):
gtk.main() gtk.main()
def _getSelected(self): def rowActivated(self, w, row, col):
selection = self.treeview.get_selection() # FIXME
model, path = selection.get_selected_rows() print 'row-activated-event', row, col
if not path:
return None
iter = model.get_iter(path[0]) def getSelected(self):
index = model.get_value(iter, 1) index = self.treeview.getSelected()
if index < 0: if index < 0:
return None return None
return self.all_keys[index] return self.all_keys[index]
def row_activated(self, w, row, col): def showSelected(self, w):
print 'row_activated_event', row, col key = self.getSelected()
def treeview_show_selected(self, w):
key = self._getSelected()
self.updatePreview(key) self.updatePreview(key)
def _create_tree_model(self, manager, key): def _createStore(self, manager, key):
self.all_keys = [] self.all_keys = []
index = 0 index = 0
# #
@ -156,18 +137,18 @@ class SelectTileDialogWithPreview(MfxDialog):
def updatePreview(self, key): def updatePreview(self, key):
##print 'updatePreview:', key ##print 'updatePreview:', key, type(key)
if key is None: if key is None:
return return
if key == self.preview_key: if key == self.preview_key:
return return
canvas = self.preview canvas = self.preview
canvas.deleteAllItems() ##canvas.deleteAllItems()
if type(key) is str: if type(key) is str:
# solid color # solid color
canvas.config(bg=key) canvas.config(bg=key)
##canvas.setTile(None) canvas.setBackgroundImage(None)
##canvas.setTextColor(None) canvas.setTextColor(None)
self.preview_key = key self.preview_key = key
self.table_color = key self.table_color = key
else: else:
@ -186,7 +167,6 @@ class SelectTileDialogWithPreview(MfxDialog):
resizable=1, resizable=1,
padx=10, pady=10, padx=10, pady=10,
width=600, height=400, width=600, height=400,
##~ buttonpadx=10, buttonpady=5,
) )
return MfxDialog.initKw(self, kw) return MfxDialog.initKw(self, kw)
@ -196,12 +176,11 @@ class SelectTileDialogWithPreview(MfxDialog):
c = '#%02x%02x%02x' % (c.red/256, c.green/256, c.blue/256) c = '#%02x%02x%02x' % (c.red/256, c.green/256, c.blue/256)
d.destroy() d.destroy()
self.updatePreview(c) self.updatePreview(c)
selection = self.treeview.get_selection() self.treeview.unselectAll()
selection.unselect_all()
def createColorsel(self): def createColorsel(self):
win = gtk.ColorSelectionDialog('Select table color') win = gtk.ColorSelectionDialog(_('Select table color'))
win.help_button.destroy() win.help_button.destroy()
win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
if type(self.preview_key) is str: if type(self.preview_key) is str:
@ -222,7 +201,7 @@ class SelectTileDialogWithPreview(MfxDialog):
self.createColorsel() self.createColorsel()
return return
if b == 0: if b == 0:
self.key = self._getSelected() self.key = self.getSelected()
if not self.key: if not self.key:
self.key = self.preview_key self.key = self.preview_key
self.status = 0 self.status = 0

View file

@ -76,19 +76,17 @@ class _CanvasItem:
def __init__(self, canvas): def __init__(self, canvas):
self.canvas = canvas self.canvas = canvas
canvas._all_items.append(self) canvas._all_items.append(self)
self._group = None
def addtag(self, group): def addtag(self, group):
##print self, 'addtag' ##print self, 'addtag'
##~ assert isinstance(group._item, CanvasGroup) ##~ assert isinstance(group._item, CanvasGroup)
self._item.reparent(group._item) self._item.reparent(group._item)
self._group = group
def dtag(self, group): def dtag(self, group):
##print self, 'dtag' ##print self, 'dtag'
##~ assert isinstance(group._item, CanvasGroup) ##~ assert isinstance(group._item, CanvasGroup)
##self._item.reparent(self.canvas.root()) ##self._item.reparent(self.canvas.root())
self._group = None pass
def bind(self, sequence, func, add=None): def bind(self, sequence, func, add=None):
bind(self._item, sequence, func, add) bind(self._item, sequence, func, add)
@ -103,33 +101,23 @@ class _CanvasItem:
self._item = None self._item = None
def lower(self, positions=None): def lower(self, positions=None):
print "lower", self._item, positions return # used for reordered shadow; don't need?
if positions is None: ## if positions is None:
if self._group: ## self._item.lower_to_bottom()
self._group._item.lower_to_bottom() ## self._item.get_property('parent').raise_to_top()
##self._item.lower_to_bottom() ## else:
else: ## ##~ assert type(positions) is types.IntType and positions > 0
self._item.lower_to_bottom() ## self._item.lower(positions)
else:
print self, 'lower', positions
##~ assert type(positions) is types.IntType and positions > 0
self._item.lower(positions)
def tkraise(self, positions=None): def tkraise(self, positions=None):
##print "tkraise", self._group, self._item.get_property('parent') #self._item, positions ##print 'tkraise', positions
if positions is None: if positions is None:
self._item.raise_to_top() self._item.raise_to_top()
self._item.get_property('parent').raise_to_top() self._item.get_property('parent').raise_to_top()
## if self._group:
## self._group._item.raise_to_top()
## ##self._item.raise_to_top()
## else:
## self._item.raise_to_top()
else: else:
print self, 'tkraise', positions print self, 'tkraise', positions # don't used?
##~ assert type(positions) is types.IntType and positions > 0 ##~ assert type(positions) is types.IntType and positions > 0
##~ self._item.raise_(positions) self._item.raise_(positions)
self._item.raise_to_top()
def move(self, x, y): def move(self, x, y):
self._item.move(x, y) self._item.move(x, y)
@ -165,6 +153,7 @@ class MfxCanvasImage(_CanvasItem):
width=image.width(), width=image.width(),
height=image.height(), height=image.height(),
anchor=anchor) anchor=anchor)
self._item.show()
def config(self, image): def config(self, image):
##~ assert isinstance(image.im, GdkImlib.Image) ##~ assert isinstance(image.im, GdkImlib.Image)
@ -194,16 +183,19 @@ class MfxCanvasLine(_CanvasItem):
self._item = canvas.root().add(gnome.canvas.CanvasLine, self._item = canvas.root().add(gnome.canvas.CanvasLine,
points=points, **kwargs) points=points, **kwargs)
self._item.show() self._item.show()
canvas.show_all() #canvas.show_all()
class MfxCanvasRectangle(_CanvasItem): class MfxCanvasRectangle(_CanvasItem):
def __init__(self, canvas, x1, y1, x2, y2, width, fill, outline): def __init__(self, canvas, x1, y1, x2, y2,
width=0, fill=None, outline=None):
_CanvasItem.__init__(self, canvas) _CanvasItem.__init__(self, canvas)
kw = {'x1': x1, 'x2': x2, 'y1': y1, 'y2': y2, 'width_pixels': width} kw = {'x1': x1, 'x2': x2, 'y1': y1, 'y2': y2}
if width: kw['width_pixels'] = width
if fill: kw['fill_color'] = fill if fill: kw['fill_color'] = fill
if outline: kw['outline_color'] = outline if outline: kw['outline_color'] = outline
self._item = canvas.root().add(gnome.canvas.CanvasRect, **kw) self._item = canvas.root().add(gnome.canvas.CanvasRect, **kw)
self._item.show()
class MfxCanvasText(_CanvasItem): class MfxCanvasText(_CanvasItem):
@ -223,6 +215,7 @@ class MfxCanvasText(_CanvasItem):
self[k] = v self[k] = v
self.text_format = None self.text_format = None
canvas._text_items.append(self) canvas._text_items.append(self)
self._item.show()
def __setitem__(self, key, value): def __setitem__(self, key, value):
if key == 'fill': if key == 'fill':
@ -241,7 +234,7 @@ class MfxCanvasText(_CanvasItem):
def __getitem__(self, key): def __getitem__(self, key):
if key == 'text': if key == 'text':
# FIXME # FIXME
return "" return self._item.get_property('text')
else: else:
raise AttributeError, key raise AttributeError, key
cget = __getitem__ cget = __getitem__
@ -330,12 +323,12 @@ class MfxCanvas(gnome.canvas.Canvas):
def configure(self, **kw): def configure(self, **kw):
height, width = -1, -1 height, width = -1, -1
for k, v in kw.items(): for k, v in kw.items():
if k == "background" or k == "bg": if k in ("background", "bg"):
##print 'configure: bg:', v ##print 'configure: bg:', v
c = self.get_colormap().alloc_color(v) c = self.get_colormap().alloc_color(v)
self.style.bg[gtk.STATE_NORMAL] = c self.style.bg[gtk.STATE_NORMAL] = c
##~ self.set_style(self.style) ##~ self.set_style(self.style)
self.queue_draw() ##~ self.queue_draw()
elif k == "cursor": elif k == "cursor":
##~ w = self.window ##~ w = self.window
##~ if w: ##~ if w:
@ -445,10 +438,15 @@ class MfxCanvas(gnome.canvas.Canvas):
self.realize() self.realize()
##return False ##return False
self.setBackgroundImage(filename, stretch) gtk.idle_add(self.setBackgroundImage, filename, stretch)
def setBackgroundImage(self, filename, stretch): def setBackgroundImage(self, filename, stretch=False):
print 'setBackgroundImage', filename print 'setBackgroundImage', filename
if filename is None:
if self.__tileimage:
self.__tileimage.destroy()
self.__tileimage = None
return
width, height = self.get_size() width, height = self.get_size()
pixbuf = gtk.gdk.pixbuf_new_from_file(filename) pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
@ -509,6 +507,19 @@ class MfxCanvas(gnome.canvas.Canvas):
self.update_now() self.update_now()
pass pass
def updateAll(self):
print 'Canvas - updateAll',
for i in self._all_items:
i._item.hide()
self.update_now()
n = 0
for i in self._all_items:
i._item.show()
print n, i
n += 1
self.update_now()
#self.window.invalidate_rect((0, 0, 400, 400), True)
def grid(self, *args, **kw): def grid(self, *args, **kw):
self.top.table.attach(self, self.top.table.attach(self,

View file

@ -31,9 +31,12 @@
# imports # imports
import sys ##import sys
from gtk import gdk from gtk import gdk
from gtk import ANCHOR_NW, ANCHOR_SW, ANCHOR_NE, ANCHOR_SE
# /*********************************************************************** # /***********************************************************************
# // constants # // constants

View file

@ -51,8 +51,8 @@ from pysollib.mfxutil import kwdefault, KwStruct
class _MyDialog(gtk.Dialog): class _MyDialog(gtk.Dialog):
def __init__(self): def __init__(self):
gtk.Dialog.__init__(self) gtk.Dialog.__init__(self)
style = self.get_style().copy() ##~ style = self.get_style().copy()
self.set_style(style) ##~ self.set_style(style)
self.connect("destroy", self.quit) self.connect("destroy", self.quit)
self.connect("delete_event", self.quit) self.connect("delete_event", self.quit)

View file

@ -124,17 +124,24 @@ class _MfxToplevel(gtk.Window):
# FIXME # FIXME
return gdk.LEFT_PTR return gdk.LEFT_PTR
return self.get_window().get_cursor(v) return self.get_window().get_cursor(v)
elif attr in ("background", "bg"):
c = self.style.bg[gtk.STATE_NORMAL]
c = '#%02x%02x%02x' % (c.red/256, c.green/256, c.blue/256)
return c
print "Toplevel cget:", attr print "Toplevel cget:", attr
##~ raise AttributeError, attr ##~ raise AttributeError, attr
return None
def configure(self, **kw): def configure(self, **kw):
height, width = -1, -1 height, width = -1, -1
for k, v in kw.items(): for k, v in kw.items():
if k == "background" or k == "bg": if k in ("background", "bg"):
c = self.get_colormap().alloc_color(v) ##print "Toplevel configure: bg"
self.style.bg[gtk.STATE_NORMAL] = c ##~ c = self.get_colormap().alloc_color(v)
##~ self.style.bg[gtk.STATE_NORMAL] = c
##~ self.set_style(self.style) ##~ self.set_style(self.style)
self.queue_draw() ##~ self.queue_draw()
pass
elif k == "cursor": elif k == "cursor":
self.setCursor(v) self.setCursor(v)
elif k == "height": elif k == "height":

View file

@ -33,7 +33,7 @@
## ##
##---------------------------------------------------------------------------## ##---------------------------------------------------------------------------##
__all__ = ['SelectCardsetByTypeDialogWithPreview'] __all__ = ['SelectCardsetDialogWithPreview']
# imports # imports
import os, re, sys, types, Tkinter import os, re, sys, types, Tkinter