mirror of https://github.com/kivy/kivy.git
Merge remote-tracking branch 'upstream/master' into uix-listview
This commit is contained in:
commit
29ff3259e9
|
@ -0,0 +1,19 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
# command to install dependencies
|
||||
before_install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install python-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsdl1.2-dev libsmpeg-dev python-numpy libportmidi-dev ffmpeg libswscale-dev libavformat-dev libavcodec-dev libjpeg-dev libtiff4-dev libx11-6 libX11-dev
|
||||
- sudo apt-get install python-setuptools python-opengl gstreamer0.10-plugins-good build-essential libgl1-mesa-dev libgles2-mesa-dev mercurial
|
||||
- sudo apt-get install xvfb
|
||||
|
||||
install:
|
||||
- pip install hg+http://bitbucket.org/pygame/pygame
|
||||
- pip install --upgrade cython pil --use-mirrors
|
||||
- make
|
||||
|
||||
# command to run tests
|
||||
script:
|
||||
- xvfb-run -s "+extension GLX" make test
|
|
@ -16,7 +16,7 @@ it will be generated like this:
|
|||
|
||||
.. image:: images/api-button.jpg
|
||||
|
||||
It should be read like this: the "Button" class is into the "kivy.uix.button"
|
||||
It should be read like this: the "Button" class is in the "kivy.uix.button"
|
||||
module. So if you want to import that class in your code, write that::
|
||||
|
||||
from kivy.uix.button import Button
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
|
@ -106,8 +106,8 @@ def callback_signature(app, what, name, obj, options, signature,
|
|||
|
||||
def setup(app):
|
||||
import kivy
|
||||
sys.path += [join(dirname(kivy.__file__), 'tools', 'highlight', 'pygments')]
|
||||
from lexer_kivy import KivyLexer
|
||||
sys.path += [join(dirname(kivy.__file__), 'extras')]
|
||||
from highlight import KivyLexer
|
||||
|
||||
app.add_lexer('kv', KivyLexer())
|
||||
app.add_autodocumenter(CythonMethodDocumenter)
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,18 @@
|
|||
This is the Kivy Catalog viewer. It serves two purposes:
|
||||
|
||||
1. To showcase the various widgets available in Kivy
|
||||
2. To allow interactive editing of Kivy language files
|
||||
to get immediate feedback as to how they work
|
||||
|
||||
To use it, you'll need to install Kivy and it's dependencies
|
||||
a la http://kivy.org/docs/installation/installation.html Then run
|
||||
python main.py and browse or edit widgets to your heart's content.
|
||||
|
||||
Known bugs:
|
||||
* The DropDown item I had tested completely crashes Kivy
|
||||
* The GridLayout example could use some extra features
|
||||
* If you try to start the app with focused set to true, weird stuff happens.
|
||||
but it works fine if you set focused to true and press render.
|
||||
* Video playback doesn't work for me, but this may be a dependency issue
|
||||
* Popups are displayed inline
|
||||
* Some widgets are still missing
|
|
@ -0,0 +1,15 @@
|
|||
#:kivy 1.4
|
||||
|
||||
AnchorLayout:
|
||||
anchor_x: "right"
|
||||
anchor_y: "bottom"
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: .4, .2
|
||||
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint: .2, .2
|
|
@ -0,0 +1,14 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
padding: 20
|
||||
spacing: 10
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: 1, None
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: 1, 0.5
|
||||
Button:
|
||||
text: "Button 3"
|
|
@ -0,0 +1,27 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Button:
|
||||
text: "Button 1"
|
||||
Button:
|
||||
text: "Button 2"
|
||||
font_size: 24
|
||||
Button:
|
||||
text: "Button 3"
|
||||
background_color: .7, .7, 1, 1
|
||||
Button:
|
||||
text: "Button 4"
|
||||
on_press: self.text = 'pressed'
|
||||
on_release: self.text = 'Button 4'
|
||||
ToggleButton:
|
||||
text: "A toggle button"
|
||||
ToggleButton:
|
||||
text: "a toggle button in a group"
|
||||
group: "money"
|
||||
ToggleButton:
|
||||
text: "A toggle in the down state"
|
||||
state: "down"
|
||||
ToggleButton:
|
||||
text: "another toggle button in a group"
|
||||
group: "money"
|
|
@ -0,0 +1,27 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
CheckBox:
|
||||
Label:
|
||||
text: "A checkbox"
|
||||
active: True
|
||||
CheckBox:
|
||||
Label:
|
||||
text: "Another checkbox"
|
||||
CheckBox:
|
||||
group: "money"
|
||||
Label:
|
||||
text: "A radio in a group"
|
||||
CheckBox:
|
||||
group: "money"
|
||||
Label:
|
||||
text: "Another radio in same group"
|
||||
active: True
|
||||
Switch:
|
||||
Label:
|
||||
text: "A Switch"
|
||||
Switch:
|
||||
active: True
|
||||
Label:
|
||||
text: "An active switch"
|
|
@ -0,0 +1,19 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
# Double as a Tabbed Panel Demo!
|
||||
TabbedPanel:
|
||||
tab_pos: "top_right"
|
||||
default_tab_text: "List View"
|
||||
default_tab_content: list_view_tab
|
||||
|
||||
TabbedPanelHeader:
|
||||
text: 'Icon View'
|
||||
content: icon_view_tab
|
||||
|
||||
FileChooserListView:
|
||||
id: list_view_tab
|
||||
|
||||
FileChooserIconView:
|
||||
id: icon_view_tab
|
||||
show_hidden: True
|
|
@ -0,0 +1,16 @@
|
|||
#:kivy 1.4
|
||||
|
||||
FloatLayout:
|
||||
Button:
|
||||
text: "Button 1"
|
||||
pos: 100, 100
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 2"
|
||||
pos: 200, 200
|
||||
size_hint: .4, .2
|
||||
|
||||
Button:
|
||||
text: "Button 3"
|
||||
pos_hint: {'x': .8, 'y': .6}
|
||||
size_hint: .2, .2
|
|
@ -0,0 +1,20 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint_x: None
|
||||
width: 100
|
||||
Button:
|
||||
text: "Button 2"
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint_x: None
|
||||
Button:
|
||||
text: "Button 4"
|
||||
Button:
|
||||
text: "Button 5"
|
||||
Button:
|
||||
text: "Button 6"
|
||||
size_hint_x: None
|
|
@ -0,0 +1,21 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
rows: 2
|
||||
Label:
|
||||
text: "Label 1"
|
||||
Label:
|
||||
text: "Label with\nmultiple lines"
|
||||
Label:
|
||||
text: "Label [color=ff3333]with[/color] [color=3333ff][b]markup[/b][/color]"
|
||||
markup: True
|
||||
Label:
|
||||
text: "Label with [ref=reference]reference[/ref]"
|
||||
markup: True
|
||||
on_ref_press: self.text = "ref clicked"
|
||||
Label:
|
||||
text: "different font"
|
||||
bold: True
|
||||
font_name: "DroidSansMono.ttf"
|
||||
font_size: 32
|
||||
valign: "bottom"
|
|
@ -0,0 +1,9 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
Image:
|
||||
source: "../../widgets/softboy.png"
|
||||
Video:
|
||||
source: "../../widgets/softboy.avi"
|
||||
state: "play"
|
|
@ -0,0 +1,6 @@
|
|||
#:kivy 1.4
|
||||
|
||||
Label:
|
||||
text_size: self.width-60, self.height-60
|
||||
valign: "middle"
|
||||
text: "The Kivy Catalog is an interactive showcase of Kivy Widgets defined in the Kivy language. For each widget you see, you can directly edit the .kv language syntax to see what effects your changes have on the widget. Click 'Render' or hit 'Ctrl-S' to view your changes.\n\nThere is also a playground on this tab where you can test your Kivy language code directly. This is beta software. The basics seem to work, but some widgets are missing or don't have the ideal .kv representation. Not all widgets are represented yet. It is trivial to add a new .kv file to the interface.\n\nPull requests are welcome."
|
|
@ -0,0 +1,23 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
Bubble:
|
||||
size_hint: (None, None)
|
||||
size: (150, 50)
|
||||
pos_hint: {'center_x': .5, 'y': .6}
|
||||
arrow_pos: 'bottom_mid'
|
||||
orientation: 'horizontal'
|
||||
BubbleButton:
|
||||
text: 'Click'
|
||||
BubbleButton:
|
||||
text: 'A'
|
||||
BubbleButton:
|
||||
text: 'Bubble'
|
||||
Popup:
|
||||
id: popup
|
||||
title: "An example popup"
|
||||
content: popupcontent
|
||||
Label:
|
||||
id: popupcontent
|
||||
text: "Some text\nin the popup"
|
|
@ -0,0 +1,17 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
padding: 50
|
||||
ProgressBar:
|
||||
id: bar
|
||||
value: 140
|
||||
max: 300
|
||||
Slider:
|
||||
id: slider
|
||||
max: 200
|
||||
value: 140
|
||||
on_value: bar.value = self.value
|
||||
Slider:
|
||||
orientation: 'vertical'
|
||||
on_value: slider.value = self.value
|
|
@ -0,0 +1,5 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
RstDocument:
|
||||
text: ".. _top:\n\nHello world\n===========\n\nThis is an **emphased text**, some ``interpreted text``.\nAnd this is a reference to top_::\n\n $ print 'Hello world'\n"
|
|
@ -0,0 +1,16 @@
|
|||
#:kivy 1.4
|
||||
|
||||
FloatLayout:
|
||||
Scatter:
|
||||
size_hint: None, None
|
||||
size: 100, 100
|
||||
pos: 100, 100
|
||||
Image:
|
||||
source: "../../widgets/softboy.png"
|
||||
Scatter:
|
||||
size_hint: None, None
|
||||
size: 100, 100
|
||||
pos: 100, 100
|
||||
do_rotation: False
|
||||
Label:
|
||||
text: "something"
|
|
@ -0,0 +1,10 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
Spinner:
|
||||
text: "Work"
|
||||
values: "Work", "Home", "Mobile", "Skype"
|
||||
size_hint: (None, None)
|
||||
size: (100, 44)
|
||||
# Wanted to put DropDown here, too, but it seems not to be working too well when loaded from .kv
|
|
@ -0,0 +1,25 @@
|
|||
#:kivy 1.4
|
||||
|
||||
StackLayout:
|
||||
orientation: 'tb-lr'
|
||||
padding: 10
|
||||
spacing: 5
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: .2, .4
|
||||
width: 100
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 4"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 5"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 6"
|
||||
size_hint: .2, .4
|
|
@ -0,0 +1,20 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
TextInput:
|
||||
text: "Single Line Input"
|
||||
multiline: False
|
||||
TextInput:
|
||||
text: "Text Input, start typing here\nmultiline\nsupport"
|
||||
background_color: .8, .8, 0, 1
|
||||
size_hint: 1, 3
|
||||
TextInput:
|
||||
text: "Password (but you can't see it)"
|
||||
password: True
|
||||
multiline: False
|
||||
on_text: viewer.text = self.text
|
||||
TextInput:
|
||||
id: viewer
|
||||
read_only: True
|
||||
text: "edit the password to see it here"
|
|
@ -0,0 +1,120 @@
|
|||
#:kivy 1.4
|
||||
|
||||
[ContainerToggle@ToggleButton]:
|
||||
group: "container_toggle"
|
||||
text: ctx.text
|
||||
on_press: root.parent.parent.parent.show_kv(*args)
|
||||
state: ctx.state if hasattr(ctx, "state") else "normal"
|
||||
|
||||
<Catalog>:
|
||||
language_box: language_box
|
||||
screen_manager: screen_manager
|
||||
BoxLayout:
|
||||
BoxLayout:
|
||||
size_hint: None, 1
|
||||
orientation: "vertical"
|
||||
ContainerToggle:
|
||||
text: "Welcome"
|
||||
state: "down"
|
||||
ContainerToggle:
|
||||
text: "Float Layout"
|
||||
ContainerToggle:
|
||||
text: "Box Layout"
|
||||
ContainerToggle:
|
||||
text: "Anchor Layout"
|
||||
ContainerToggle:
|
||||
text: "Grid Layout"
|
||||
ContainerToggle:
|
||||
text: "Stack Layout"
|
||||
ContainerToggle:
|
||||
text: "Buttons"
|
||||
ContainerToggle:
|
||||
text: "Labels"
|
||||
ContainerToggle:
|
||||
text: "Booleans"
|
||||
ContainerToggle:
|
||||
text: "Progress Bar"
|
||||
ContainerToggle:
|
||||
text: "Media"
|
||||
ContainerToggle:
|
||||
text: "Text"
|
||||
ContainerToggle:
|
||||
text: "Popups"
|
||||
ContainerToggle:
|
||||
text: "Selectors"
|
||||
ContainerToggle:
|
||||
text: "File Choosers"
|
||||
ContainerToggle:
|
||||
text: "Scatter"
|
||||
ContainerToggle:
|
||||
text: "ReST"
|
||||
ScreenManager:
|
||||
id: screen_manager
|
||||
Screen:
|
||||
name: "Welcome"
|
||||
PlaygroundContainer:
|
||||
Screen:
|
||||
name: "Float Layout"
|
||||
FloatLayoutContainer
|
||||
Screen:
|
||||
name: "Box Layout"
|
||||
BoxLayoutContainer:
|
||||
Screen:
|
||||
name: "Anchor Layout"
|
||||
AnchorLayoutContainer:
|
||||
Screen:
|
||||
name: "Grid Layout"
|
||||
GridLayoutContainer:
|
||||
Screen:
|
||||
name: "Stack Layout"
|
||||
StackLayoutContainer:
|
||||
Screen:
|
||||
name: "Buttons"
|
||||
ButtonContainer:
|
||||
Screen:
|
||||
name: "Labels"
|
||||
LabelContainer:
|
||||
Screen:
|
||||
name: "Booleans"
|
||||
CheckBoxContainer:
|
||||
Screen:
|
||||
name: "Progress Bar"
|
||||
ProgressBarContainer:
|
||||
Screen:
|
||||
name: "Media"
|
||||
MediaContainer:
|
||||
Screen:
|
||||
name: "Text"
|
||||
TextContainer:
|
||||
Screen:
|
||||
name: "Popups"
|
||||
PopupContainer:
|
||||
Screen:
|
||||
name: "Selectors"
|
||||
SelectorsContainer:
|
||||
Screen:
|
||||
name: "File Choosers"
|
||||
FileChooserContainer:
|
||||
Screen:
|
||||
name: "Scatter"
|
||||
ScatterContainer:
|
||||
Screen:
|
||||
name: "ReST"
|
||||
RestContainer:
|
||||
|
||||
BoxLayout:
|
||||
id: bl
|
||||
orientation: "vertical"
|
||||
size_hint: None, 1
|
||||
width: 400
|
||||
KivyRenderTextInput:
|
||||
text_size: self.width-20, self.height-20
|
||||
font_name: "DroidSansMono.ttf"
|
||||
valign: "top"
|
||||
id: language_box
|
||||
text: "This box will display the kivy language for whatever has been selected"
|
||||
Button:
|
||||
size_hint: 1, None
|
||||
height: 50
|
||||
text: "Render"
|
||||
on_press: root.change_kv(*args)
|
|
@ -0,0 +1,153 @@
|
|||
import kivy
|
||||
kivy.require('1.4.2')
|
||||
import os
|
||||
import sys
|
||||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
from kivy.lang import Builder, Parser, ParserException
|
||||
from kivy.properties import ObjectProperty
|
||||
from kivy.config import Config
|
||||
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.textinput import TextInput
|
||||
|
||||
print Config.get('graphics', 'width')
|
||||
|
||||
Config.set('graphics', 'width', '1024')
|
||||
Config.set('graphics', 'height', '768')
|
||||
|
||||
'''List of classes that need to be instantiated in the factory from .kv files.
|
||||
'''
|
||||
CONTAINER_CLASSES = [c[:-3] for c in os.listdir('container_kvs')
|
||||
if c.endswith('.kv')]
|
||||
|
||||
|
||||
class Container(BoxLayout):
|
||||
'''A container is essentially a class that loads its root from a known
|
||||
.kv file.
|
||||
|
||||
The name of the .kv file is taken from the Container's class.
|
||||
We can't just use kv rules because the class may be edited
|
||||
in the interface and reloaded by the user.
|
||||
See :meth: change_kv where this happens.
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Container, self).__init__(**kwargs)
|
||||
parser = Parser(content=file(self.kv_file).read())
|
||||
widget = Factory.get(parser.root.name)()
|
||||
Builder._apply_rule(widget, parser.root, parser.root)
|
||||
self.add_widget(widget)
|
||||
|
||||
@property
|
||||
def kv_file(self):
|
||||
'''Get the name of the kv file, a lowercase version of the class name.'''
|
||||
return os.path.join('container_kvs',
|
||||
self.__class__.__name__ + ".kv")
|
||||
|
||||
|
||||
for class_name in CONTAINER_CLASSES:
|
||||
globals()[class_name] = type(class_name, (Container,), {})
|
||||
|
||||
|
||||
class KivyRenderTextInput(TextInput):
|
||||
def _keyboard_on_key_down(self, window, keycode, text, modifiers):
|
||||
is_osx = sys.platform == 'darwin'
|
||||
# Keycodes on OSX:
|
||||
ctrl, cmd = 64, 1024
|
||||
key, key_str = keycode
|
||||
|
||||
if text and not key in (self.interesting_keys.keys() + [27]):
|
||||
# This allows *either* ctrl *or* cmd, but not both.
|
||||
if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']):
|
||||
if key == ord('s'):
|
||||
self.parent.parent.parent.change_kv(True)
|
||||
return
|
||||
|
||||
super(KivyRenderTextInput, self)._keyboard_on_key_down(
|
||||
window, keycode, text, modifiers)
|
||||
|
||||
|
||||
class Catalog(BoxLayout):
|
||||
'''Catalog of widgets. This is the root widget of the app. It contains
|
||||
a tabbed pain of widgets that can be displayed and a textbox where .kv
|
||||
language files for widgets being demoed can be edited.
|
||||
|
||||
The entire interface for the Catalog is defined in kivycatalog.kv, although
|
||||
individual containers are defined in the container_kvs directory.
|
||||
|
||||
To add a container to the catalog,
|
||||
first create the .kv file in container_kvs
|
||||
The name of the file (sans .kv) will be the name of the widget available
|
||||
inside the kivycatalog.kv
|
||||
Finally modify kivycatalog.kv to add an AccordionItem
|
||||
to hold the new widget.
|
||||
Follow the examples in kivycatalog.kv to ensure the item
|
||||
has an appropriate id and the class has been referenced.
|
||||
|
||||
You do not need to edit any python code, just .kv language files!
|
||||
'''
|
||||
language_box = ObjectProperty()
|
||||
screen_manager = ObjectProperty()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Catalog, self).__init__(**kwargs)
|
||||
self.show_kv(None)
|
||||
|
||||
def show_kv(self, object):
|
||||
'''Called when an accordionitem is collapsed or expanded. If it
|
||||
was expanded, we need to show the .kv language file associated with
|
||||
the newly revealed container.'''
|
||||
|
||||
# if object is not passed, it's initialization, we just need to load
|
||||
# the file
|
||||
if object:
|
||||
# one button must always be pressed, even if user presses it again
|
||||
if object.state == "normal":
|
||||
object.state = "down"
|
||||
|
||||
self.screen_manager.current = object.text
|
||||
|
||||
with open(self.screen_manager.current_screen.content.children[
|
||||
0].kv_file) as file:
|
||||
self.language_box.text = file.read()
|
||||
|
||||
def change_kv(self, button):
|
||||
'''Called when the update button is clicked. Needs to update the
|
||||
interface for the currently active kv widget, if there is one based
|
||||
on the kv file the user entered. If there is an error in their kv
|
||||
syntax, show a nice popup.'''
|
||||
kv_container = self.screen_manager.current_screen.content.children[0]
|
||||
try:
|
||||
parser = Parser(content=self.language_box.text.encode('utf8'))
|
||||
kv_container.clear_widgets()
|
||||
widget = Factory.get(parser.root.name)()
|
||||
Builder._apply_rule(widget, parser.root, parser.root)
|
||||
kv_container.add_widget(widget)
|
||||
except (SyntaxError, ParserException) as e:
|
||||
content = Label(text=str(e), text_size=(350, None))
|
||||
popup = Popup(title="Parse Error in Kivy Language Markup",
|
||||
content=content, text_size=(350, None),
|
||||
size_hint=(None, None), size=(400, 400))
|
||||
popup.open()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
popup = Popup(title="Boom",
|
||||
content=Label(text="Something horrible happened while parsing your Kivy Language", text_size=(350, None)),
|
||||
text_size=(350, None),
|
||||
size_hint=(None, None), size=(400, 400))
|
||||
popup.open()
|
||||
|
||||
|
||||
class KivyCatalogApp(App):
|
||||
'''The kivy App that runs the main root. All we do is build a catalog
|
||||
widget into the root.'''
|
||||
def build(self):
|
||||
return Catalog()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
KivyCatalogApp().run()
|
|
@ -0,0 +1,82 @@
|
|||
from kivy.app import App
|
||||
from kivy.extras.highlight import KivyLexer
|
||||
from kivy.factory import Factory
|
||||
import pygments
|
||||
|
||||
example_text = '''
|
||||
---------------------Python----------------------------------
|
||||
import kivy
|
||||
kivy.require('1.0.6') # replace with your current kivy version !
|
||||
from kivy.app import App
|
||||
from kivy.uix.button import Button
|
||||
|
||||
class MyApp(App):
|
||||
def build(self):
|
||||
return Button(text='Hello World')
|
||||
|
||||
if __name__ == '__main__':
|
||||
MyApp().run()
|
||||
----------------------Java------------------------------------
|
||||
|
||||
public static byte toUnsignedByte(int intVal) {
|
||||
byte byteVal;
|
||||
return (byte)(intVal & 0xFF);
|
||||
}
|
||||
---------------------kv lang-------------------------
|
||||
#:kivy 1.0
|
||||
|
||||
<YourWidget>:
|
||||
canvas:
|
||||
Color:
|
||||
rgb: .5, .5, .5
|
||||
Rectangle:
|
||||
pos: self.pos
|
||||
size: self.size
|
||||
-----------------HTML-----------------------------
|
||||
<!-- Place this tag where you want the +1 button to render. -->
|
||||
<div class="g-plusone" data-annotation="inline" data-width="300"></div>
|
||||
|
||||
<!-- Place this tag after the last +1 button tag. -->
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
|
||||
po.src = 'https://apis.google.com/js/plusone.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
|
||||
})();
|
||||
</script>
|
||||
'''
|
||||
|
||||
|
||||
class CodeInputTest(App):
|
||||
def build(self):
|
||||
b = Factory.BoxLayout(orientation='vertical')
|
||||
languages = Factory.Spinner(
|
||||
text='language',
|
||||
values=sorted(['KvLexer', ] + pygments.lexers.LEXERS.keys()),
|
||||
size_hint_y=None,
|
||||
height='30pt')
|
||||
|
||||
languages.bind(text=self.change_lang)
|
||||
b.add_widget(languages)
|
||||
|
||||
self.codeinput = Factory.CodeInput(
|
||||
lexer=KivyLexer(),
|
||||
font_name='data/fonts/DroidSansMono.ttf', font_size=12,
|
||||
text=example_text)
|
||||
|
||||
b.add_widget(self.codeinput)
|
||||
|
||||
return b
|
||||
|
||||
def change_lang(self, instance, l):
|
||||
if l == 'KvLexer':
|
||||
lx = KivyLexer()
|
||||
|
||||
else:
|
||||
lx = pygments.lexers.get_lexer_by_name(
|
||||
pygments.lexers.LEXERS[l][2][0])
|
||||
|
||||
self.codeinput.lexer = lx
|
||||
|
||||
|
||||
CodeInputTest().run()
|
|
@ -192,7 +192,7 @@ class Atlas(EventDispatcher):
|
|||
self.textures = textures
|
||||
|
||||
@staticmethod
|
||||
def create(outname, filenames, size, padding=1):
|
||||
def create(outname, filenames, size, padding=2):
|
||||
'''This method can be used to create manually an atlas from a set of
|
||||
images.
|
||||
|
||||
|
@ -204,11 +204,17 @@ class Atlas(EventDispatcher):
|
|||
List of filename to put in the atlas
|
||||
`size`: int
|
||||
Size of an atlas image
|
||||
`padding`: int, default to 1
|
||||
Padding to put around each image. Care, if you put 0, they might
|
||||
be some issues with OpenGL, because by default, Kivy texture are
|
||||
using GL_CLAMP_TO_EDGE, and the edge is another image than
|
||||
the image you'll want to display.
|
||||
`padding`: int, default to 2
|
||||
Padding to put around each image.
|
||||
|
||||
Be careful. If you're using a padding < 2, you might get issues
|
||||
with border of the images. Because of the OpenGL linearization,
|
||||
it might take the pixels of the adjacent image.
|
||||
|
||||
If you're using a padding >= 2, we'll automatically generate a
|
||||
"border" of 1px of your image, around the image. If you look at
|
||||
the result, don't be scared if the image inside it are not
|
||||
exactly the same as yours :).
|
||||
'''
|
||||
# Thanks to
|
||||
# omnisaurusgames.com/2011/06/texture-atlas-generation-using-python/
|
||||
|
@ -232,7 +238,6 @@ class Atlas(EventDispatcher):
|
|||
# the freebox tuple format is: outidx, x, y, w, h
|
||||
freeboxes = [(0, 0, 0, size, size)]
|
||||
numoutimages = 1
|
||||
padding = 1
|
||||
|
||||
# full boxes are areas where we have placed images in the atlas
|
||||
# the full box tuple format is: image, outidx, x, y, w, h, filename
|
||||
|
@ -291,7 +296,16 @@ class Atlas(EventDispatcher):
|
|||
outimages = [Image.new('RGBA', (size, size))
|
||||
for i in range(0, int(numoutimages))]
|
||||
for fb in fullboxes:
|
||||
outimages[fb[1]].paste(fb[0], (fb[2], fb[3]))
|
||||
x, y = fb[2], fb[3]
|
||||
out = outimages[fb[1]]
|
||||
out.paste(fb[0], (fb[2], fb[3]))
|
||||
w, h = fb[0].size
|
||||
if padding > 1:
|
||||
out.paste(fb[0].crop((0, 0, w, 1)), (x, y - 1))
|
||||
out.paste(fb[0].crop((0, h - 1, w, h)), (x, y + h))
|
||||
out.paste(fb[0].crop((0, 0, 1, h)), (x - 1, y))
|
||||
out.paste(fb[0].crop((w - 1, 0, w, h)), (x + w, y))
|
||||
|
||||
|
||||
# save the output images
|
||||
for idx, outimage in enumerate(outimages):
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
|
@ -1 +1 @@
|
|||
{"defaulttheme-0.png": {"player-play-overlay": [306, 396, 117, 115], "spinner_pressed": [91, 124, 29, 37], "progressbar_background": [220, 137, 24, 24], "media-playback-pause": [448, 344, 48, 48], "tab_btn_pressed": [465, 178, 32, 32], "image-missing": [399, 344, 48, 48], "filechooser_selected": [187, 393, 118, 118], "audio-volume-muted": [350, 344, 48, 48], "sliderv_background": [473, 404, 37, 41], "tab": [332, 228, 96, 32], "close": [490, 491, 20, 20], "ring": [1, 326, 185, 185], "vkeyboard_key_down": [121, 129, 32, 32], "vkeyboard_background": [187, 328, 64, 64], "checkbox_off": [300, 178, 32, 32], "bubble_arrow": [148, 162, 16, 10], "player-background": [228, 222, 103, 103], "bubble": [424, 446, 65, 65], "spinner": [61, 124, 29, 37], "sliderh_background": [148, 173, 41, 37], "audio-volume-medium": [301, 344, 48, 48], "media-playback-start": [1, 162, 48, 48], "tab_btn": [432, 178, 32, 32], "bubble_btn_pressed": [267, 178, 32, 32], "tree_closed": [490, 470, 20, 20], "switch-background": [429, 228, 83, 32], "filechooser_file": [332, 261, 64, 64], "checkbox_radio_off": [366, 178, 32, 32], "vkeyboard_key_normal": [154, 129, 32, 32], "checkbox_radio_on": [399, 178, 32, 32], "checkbox_on": [333, 178, 32, 32], "tree_opened": [490, 449, 20, 20], "button_pressed": [31, 124, 29, 37], "media-playback-stop": [50, 162, 48, 48], "audio-volume-high": [424, 397, 48, 48], "audio-volume-low": [252, 344, 48, 48], "bubble_btn": [234, 178, 32, 32], "modalview-background": [462, 271, 45, 54], "button": [1, 124, 29, 37], "progressbar": [187, 137, 32, 24], "switch-button": [190, 178, 43, 32], "filechooser_folder": [397, 261, 64, 64], "slider_cursor": [99, 162, 48, 48], "textinput_active": [1, 211, 114, 114], "textinput": [116, 214, 111, 111]}}
|
||||
{"defaulttheme-0.png": {"player-play-overlay": [309, 395, 117, 115], "spinner_pressed": [384, 170, 29, 37], "progressbar_background": [483, 183, 24, 24], "media-playback-pause": [52, 159, 48, 48], "tab_btn_pressed": [138, 125, 32, 32], "image-missing": [2, 159, 48, 48], "filechooser_selected": [189, 392, 118, 118], "audio-volume-muted": [452, 342, 48, 48], "sliderv_background": [252, 166, 37, 41], "tab": [336, 225, 96, 32], "close": [240, 137, 20, 20], "ring": [2, 325, 185, 185], "vkeyboard_key_down": [172, 125, 32, 32], "vkeyboard_background": [189, 326, 64, 64], "checkbox_off": [449, 175, 32, 32], "bubble_arrow": [495, 500, 16, 10], "player-background": [231, 220, 103, 103], "bubble": [428, 445, 65, 65], "spinner": [353, 170, 29, 37], "sliderh_background": [468, 286, 41, 37], "audio-volume-medium": [402, 342, 48, 48], "media-playback-start": [102, 159, 48, 48], "tab_btn": [104, 125, 32, 32], "bubble_btn_pressed": [415, 175, 32, 32], "tree_closed": [262, 137, 20, 20], "switch-background": [428, 411, 83, 32], "filechooser_file": [336, 259, 64, 64], "checkbox_radio_off": [36, 125, 32, 32], "vkeyboard_key_normal": [206, 125, 32, 32], "checkbox_radio_on": [70, 125, 32, 32], "checkbox_on": [2, 125, 32, 32], "tree_opened": [284, 137, 20, 20], "button_pressed": [322, 170, 29, 37], "media-playback-stop": [152, 159, 48, 48], "audio-volume-high": [302, 342, 48, 48], "audio-volume-low": [352, 342, 48, 48], "bubble_btn": [479, 225, 32, 32], "modalview-background": [255, 336, 45, 54], "button": [291, 170, 29, 37], "progressbar": [468, 260, 32, 24], "switch-button": [434, 225, 43, 32], "filechooser_folder": [402, 259, 64, 64], "slider_cursor": [202, 159, 48, 48], "textinput_active": [2, 209, 114, 114], "textinput": [118, 212, 111, 111]}}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
'''Pygments lexer for kv language
|
||||
'''
|
||||
from pygments.lexer import RegexLexer, bygroups, using
|
||||
from pygments.lexers.agile import PythonLexer
|
||||
from pygments import highlight
|
|
@ -81,6 +81,7 @@ r('Bubble', module='kivy.uix.bubble')
|
|||
r('BubbleButton', module='kivy.uix.bubble')
|
||||
r('Camera', module='kivy.uix.camera')
|
||||
r('Carousel', module='kivy.uix.carousel')
|
||||
r('CodeInput', module='kivy.uix.codeinput')
|
||||
r('CheckBox', module='kivy.uix.checkbox')
|
||||
r('DropDown', module='kivy.uix.dropdown')
|
||||
r('FloatLayout', module='kivy.uix.floatlayout')
|
||||
|
|
|
@ -7,10 +7,10 @@ Input Postprocessing
|
|||
__all__ = ('kivy_postproc_modules', )
|
||||
|
||||
import os
|
||||
from doubletap import InputPostprocDoubleTap
|
||||
from ignorelist import InputPostprocIgnoreList
|
||||
from retaintouch import InputPostprocRetainTouch
|
||||
from dejitter import InputPostprocDejitter
|
||||
from kivy.input.postproc.doubletap import InputPostprocDoubleTap
|
||||
from kivy.input.postproc.ignorelist import InputPostprocIgnoreList
|
||||
from kivy.input.postproc.retaintouch import InputPostprocRetainTouch
|
||||
from kivy.input.postproc.dejitter import InputPostprocDejitter
|
||||
|
||||
# Mapping of ID to module
|
||||
kivy_postproc_modules = {}
|
||||
|
|
|
@ -43,7 +43,7 @@ can be quickly listed by using the '.' operator and pressing 'tab.' Try this
|
|||
code in an Ipython shell.::
|
||||
|
||||
from kivy.interactive import InteractiveLauncher
|
||||
from kivy.app imort App
|
||||
from kivy.app import App
|
||||
from kivy.uix.widget import Widget
|
||||
from kivy.graphics import Color, Ellipse
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from common import GraphicUnitTest
|
||||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
|
||||
class FileChooserTestCase(GraphicUnitTest):
|
||||
|
|
|
@ -5,7 +5,7 @@ Graphics tests
|
|||
Testing the simple vertex instructions
|
||||
'''
|
||||
|
||||
from common import GraphicUnitTest
|
||||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
|
||||
class VertexInstructionTestCase(GraphicUnitTest):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from common import GraphicUnitTest
|
||||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
|
||||
class Issue609(GraphicUnitTest):
|
||||
|
|
|
@ -3,7 +3,7 @@ Anchor layout unit test
|
|||
=======================
|
||||
'''
|
||||
|
||||
from common import GraphicUnitTest
|
||||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
|
||||
class UIXAnchorLayoutTestcase(GraphicUnitTest):
|
||||
|
|
|
@ -6,7 +6,7 @@ Order matter.
|
|||
On the screen, most of example must have the red->blue->green order.
|
||||
'''
|
||||
|
||||
from common import GraphicUnitTest
|
||||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
|
||||
class UIXBoxLayoutTestcase(GraphicUnitTest):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from common import GraphicUnitTest
|
||||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
|
||||
class UIXWidgetTestCase(GraphicUnitTest):
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Code Input
|
||||
==========
|
||||
|
||||
.. versionadded:: 1.5.0
|
||||
|
||||
.. image:: images/codeinput.jpg
|
||||
|
||||
|
||||
The :class:`CodeInput` provides a box of editable highlited text, like the ones
|
||||
shown in the image.
|
||||
|
||||
It supports all the features supported by the :class:`~kivy.uix.textinput` and
|
||||
Code highliting for `languages supported by pygments
|
||||
<http://pygments.org/docs/lexers/>`_ along with `KivyLexer` for `KV Language`
|
||||
highliting.
|
||||
|
||||
Usage example
|
||||
-------------
|
||||
|
||||
To create a CodeInput with highliting for `KV language`::
|
||||
|
||||
from kivy.uix.codeinput import CodeInput
|
||||
from kivy.extras.highlight import KivyLexer
|
||||
codeinput = CodeInput(lexer=KivyLexer())
|
||||
|
||||
To create a CodeInput with highliting for `Cython`::
|
||||
|
||||
from kivy.uix.codeinput import CodeInput
|
||||
from pygments.lexers import CythonLexer
|
||||
codeinput = CodeInput(lexer=CythonLexer())
|
||||
|
||||
'''
|
||||
|
||||
__all__ = ('CodeInput', )
|
||||
|
||||
from pygments import highlight
|
||||
from pygments import lexers
|
||||
from pygments.formatters import BBCodeFormatter
|
||||
|
||||
from kivy.uix.textinput import TextInput
|
||||
from kivy.core.text.markup import MarkupLabel as Label
|
||||
from kivy.cache import Cache
|
||||
from kivy.properties import ObjectProperty
|
||||
|
||||
Cache_get = Cache.get
|
||||
Cache_append = Cache.append
|
||||
|
||||
# TODO: fix empty line rendering
|
||||
# TODO: color chooser for keywords/strings/...
|
||||
|
||||
|
||||
class CodeInput(TextInput):
|
||||
'''CodeInput class, used for displaying highlited code.
|
||||
'''
|
||||
|
||||
lexer = ObjectProperty(None)
|
||||
'''This holds the selected Lexer used by pygments to highlite the code
|
||||
|
||||
|
||||
:data:`lexer` is a :class:`~kivy.properties.ObjectProperty` defaults to
|
||||
`PythonLexer`
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.formatter = BBCodeFormatter()
|
||||
self.lexer = lexers.PythonLexer()
|
||||
self.text_color = (0, 0, 0, 1)
|
||||
self._label_cached = Label()
|
||||
super(CodeInput, self).__init__(**kwargs)
|
||||
self._line_options = kw = self._get_line_options()
|
||||
self._label_cached = Label(**kw)
|
||||
#use text_color as foreground color
|
||||
text_color = kwargs.get('foreground_color')
|
||||
if text_color:
|
||||
self.text_color = (text_color[0], text_color[1], text_color[2],
|
||||
text_color[3])
|
||||
# set foreground to white to allow text colors to show
|
||||
# use text_color as the default color in bbcodes
|
||||
self.foreground_color = [1, 1, 1, 1]
|
||||
if not kwargs.get('background_color'):
|
||||
self.background_color = [.9, .92, .92, 1]
|
||||
|
||||
def _create_line_label(self, text):
|
||||
# Create a label from a text, using line options
|
||||
ntext = text.replace('\n', '').replace('\t', ' ' * self.tab_width)
|
||||
if self.password:
|
||||
ntext = '*' * len(ntext)
|
||||
ntext = self._get_bbcode(ntext)
|
||||
kw = self._get_line_options()
|
||||
cid = '%s\0%s' % (ntext, str(kw))
|
||||
texture = Cache_get('textinput.label', cid)
|
||||
|
||||
if not texture:
|
||||
# FIXME right now, we can't render very long line...
|
||||
# if we move on "VBO" version as fallback, we won't need to do this.
|
||||
# try to found the maximum text we can handle
|
||||
label = Label(text=ntext, **kw)
|
||||
if text.find('\n') > 0:
|
||||
label.text = ''
|
||||
else:
|
||||
label.text = ntext
|
||||
try:
|
||||
label.refresh()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# ok, we found it.
|
||||
texture = label.texture
|
||||
Cache_append('textinput.label', cid, texture)
|
||||
label.text = ''
|
||||
return texture
|
||||
|
||||
def _get_line_options(self):
|
||||
kw = super(CodeInput, self)._get_line_options()
|
||||
kw['markup'] = True
|
||||
kw['valign'] = 'top'
|
||||
return kw
|
||||
|
||||
def _get_bbcode(self, ntext):
|
||||
# get bbcoded text for python
|
||||
try:
|
||||
ntext[0]
|
||||
# replace brackets with special chars that aren't highlighted
|
||||
# by pygment. can't use &bl; ... cause & is highlighted
|
||||
# if at some time support for braille is added then replace these
|
||||
# characters with something else
|
||||
ntext = ntext.replace('[', u'⣿;').replace(']', u'⣾;')
|
||||
ntext = highlight(ntext, self.lexer, self.formatter)
|
||||
ntext = ntext.replace(u'⣿;', '&bl;').replace(u'⣾;', '&br;')
|
||||
# replace special chars with &bl; and &br;
|
||||
ntext = ''.join(('[color=rgba', str(self.text_color), ']',
|
||||
ntext, '[/color]'))
|
||||
ntext = ntext.replace('\n', '')
|
||||
return ntext
|
||||
except IndexError:
|
||||
return ''
|
||||
|
||||
# overriden to prevent cursor position off screen
|
||||
def _cursor_offset(self):
|
||||
'''Get the cursor x offset on the current line
|
||||
'''
|
||||
offset = 0
|
||||
try:
|
||||
if self.cursor_col:
|
||||
offset = self._get_text_width(
|
||||
self._lines[self.cursor_row][:self.cursor_col])
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
return offset
|
||||
|
||||
def on_lexer(self, instance, value):
|
||||
self._trigger_refresh_text()
|
||||
|
||||
if __name__ == '__main__':
|
||||
from kivy.extras.highlight import KivyLexer
|
||||
from kivy.app import App
|
||||
|
||||
class CodeInputTest(App):
|
||||
def build(self):
|
||||
return CodeInput(lexer=KivyLexer(),
|
||||
font_name='data/fonts/DroidSansMono.ttf', font_size=12,
|
||||
text='''
|
||||
#:kivy 1.0
|
||||
|
||||
<YourWidget>:
|
||||
canvas:
|
||||
Color:
|
||||
rgb: .5, .5, .5
|
||||
Rectangle:
|
||||
pos: self.pos
|
||||
size: self.size''')
|
||||
|
||||
CodeInputTest().run()
|
Loading…
Reference in New Issue