Skip to content

Commit

Permalink
Implement TabArray class (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
PromyLOPh authored Oct 21, 2023
1 parent 0292399 commit 1d12c01
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 16 deletions.
20 changes: 10 additions & 10 deletions docs/binding-progress.rst
Original file line number Diff line number Diff line change
Expand Up @@ -311,19 +311,19 @@ ______________________
* PangoAttrList
* PANGO_TYPE_ATTR_LIST
* PangoAttrIterator
* pango_tab_array_new ()
* pango_tab_array_new ()
* pango_tab_array_new_with_positions ()
* pango_tab_array_copy ()
* pango_tab_array_free ()
* pango_tab_array_get_size ()
* pango_tab_array_resize ()
* pango_tab_array_set_tab ()
* pango_tab_array_get_tab ()
* pango_tab_array_get_tabs ()
* pango_tab_array_copy ()
* pango_tab_array_free ()
* pango_tab_array_get_size ()
* pango_tab_array_resize ()
* pango_tab_array_set_tab ()
* pango_tab_array_get_tab ()
* pango_tab_array_get_tabs ()
* pango_tab_array_get_positions_in_pixels ()
* PangoTabArray
* PangoTabArray
* PANGO_TYPE_TAB_ARRAY
* PangoTabAlign
* PangoTabAlign
* PANGO_TYPE_TAB_ALIGN
* ✔︎ pango_layout_new ()
* pango_layout_copy ()
Expand Down
12 changes: 10 additions & 2 deletions docs/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,15 @@ Tab Stops

Structures for storing tab stops.

API not implemented yet.
TabArray
________

.. autoclass:: TabArray

TabAlign
________

.. autoclass:: TabAlign

Text Attribute Markup
=====================
Expand Down Expand Up @@ -230,4 +238,4 @@ ________________
Pango Object
____________

.. autoclass:: PangoObject
.. autoclass:: PangoObject
1 change: 1 addition & 0 deletions pangocffi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def _dlopen(dl_name: str, generated_ffi, names: List[str]):
from .glyph_item_iter import GlyphItemIter # noqa
from .attribute import Attribute # noqa
from .attr_list import AttrList # noqa
from .tabarray import TabArray # noqa
from .layout_run import LayoutRun # noqa
from .layout_iter import LayoutIter # noqa
from .layout import Layout # noqa
Expand Down
4 changes: 2 additions & 2 deletions pangocffi/c_definitions_glib.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ typedef int gint32;
typedef gint gboolean;
typedef char gchar;
typedef unsigned char guchar;
typedef ... gunichar;
typedef guint32 gunichar;
typedef void* gpointer;
typedef ... gconstpointer;
typedef ... GObject;
Expand All @@ -22,4 +22,4 @@ typedef ... GMarkupParseContext;
typedef ... GTypeModule;

void g_object_unref (gpointer object);
void g_free (gpointer mem);
void g_free (gpointer mem);
8 changes: 7 additions & 1 deletion pangocffi/c_definitions_pango.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,10 @@ void pango_script_iter_free (PangoScriptIter *iter);
PangoLanguage *pango_script_get_sample_language (PangoScript script) ;
typedef enum
{
PANGO_TAB_LEFT
PANGO_TAB_LEFT,
PANGO_TAB_RIGHT,
PANGO_TAB_CENTER,
PANGO_TAB_DECIMAL
} PangoTabAlign;
PangoTabArray *pango_tab_array_new (gint initial_size,
gboolean positions_in_pixels);
Expand All @@ -1092,6 +1095,9 @@ void pango_tab_array_get_tabs (PangoTabArray *tab_array,
PangoTabAlign **alignments,
gint **locations);
gboolean pango_tab_array_get_positions_in_pixels (PangoTabArray *tab_array);
void pango_tab_array_set_positions_in_pixels (PangoTabArray *tab_array, gboolean positions_in_pixels);
void pango_tab_array_set_decimal_point (PangoTabArray *tab_array, int tab_index, gunichar decimal_point);
gunichar pango_tab_array_get_decimal_point (PangoTabArray *tab_array, int tab_index);
int pango_units_from_double (double d) ;
double pango_units_to_double (int i) ;
void pango_extents_to_pixels (PangoRectangle *inclusive,
Expand Down
31 changes: 31 additions & 0 deletions pangocffi/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,34 @@ class Underline(Enum):
mispelling; in some cases a contrasting color may
automatically be used. This type of underlining is available
since Pango 1.4."""


class TabAlign(Enum):
"""
:class:`TabAlign` specifies where the text appears relative to the
tab stop position.
"""

LEFT = pango.PANGO_TAB_LEFT
"""
The text appears to the right of the tab stop position.
"""

RIGHT = pango.PANGO_TAB_RIGHT
"""
The text appears to the left of the tab stop position until the
available space is filled. Since: 1.50
"""

CENTER = pango.PANGO_TAB_CENTER
"""
The text is centered at the tab stop position until the available
space is filled. Since: 1.50
"""

DECIMAL = pango.PANGO_TAB_DECIMAL
"""
Text before the first occurrence of the decimal point character
appears to the left of the tab stop position (until the available
space is filled), the rest to the right. Since: 1.50
"""
14 changes: 13 additions & 1 deletion pangocffi/layout.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from . import pango, gobject, ffi, PangoObject
from . import Context, FontDescription, AttrList
from . import Context, FontDescription, AttrList, TabArray
from . import Alignment, Rectangle, EllipsizeMode, WrapMode
from pangocffi import LayoutIter
from typing import Tuple, Optional
Expand Down Expand Up @@ -165,6 +165,18 @@ def _del_attributes(self) -> None:
:param attrs: a :class:`AttrList`
"""

def _get_tabs(self) -> TabArray:
tabs_pointer = pango.pango_layout_get_tabs(self._pointer)
return TabArray(tabs_pointer)

def _set_tabs(self, tabs: TabArray) -> None:
pango.pango_layout_set_tabs(self._pointer, tabs._pointer)

tabs: str = property(_get_tabs, _set_tabs)
"""
The tab stops for this layout.
"""

def apply_markup(self, markup: str) -> None:
"""
Sets the layout text and attribute list from marked-up text.
Expand Down
86 changes: 86 additions & 0 deletions pangocffi/tabarray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from . import pango, ffi, PangoObject, TabAlign
from typing import List, Tuple, Optional


class TabArray(PangoObject):

_INIT_METHOD = pango.pango_tab_array_new
_GC_METHOD = pango.pango_tab_array_free
_COPY_METHOD = pango.pango_tab_array_copy

def __init__(self):
return super().__init__(None, 0, False)

def __len__(self):
return pango.pango_tab_array_get_size(self._pointer)

def _get_tabs(self) -> List[Tuple[TabAlign, int]]:
size = len(self)
alignments = ffi.new("PangoTabAlign**")
locations = ffi.new("gint**")
pango.pango_tab_array_get_tabs(self._pointer, alignments, locations)
if alignments[0] == ffi.NULL or locations[0] == ffi.NULL:
return []
else:
return [(TabAlign(alignments[0][i]), locations[0][i])
for i in range(size)]

def _set_tabs(self, tabs: List[Tuple[TabAlign, int]]) -> None:
pango.pango_tab_array_resize(self._pointer, len(tabs))
for i in range(len(tabs)):
pango.pango_tab_array_set_tab(self._pointer, i, tabs[i][0].value,
tabs[i][1])

tabs: str = property(_get_tabs, _set_tabs)
"""
Alignment and location of the tabs.
"""

def _get_decimal_point(self) -> List[Optional[str]]:
size = len(self)
ret = []
for i in range(size):
decimal_point = pango.pango_tab_array_get_decimal_point(
self._pointer, i)
if decimal_point == 0:
ret.append(None)
else:
ret.append(chr(decimal_point))
return ret

def _set_decimal_point(self, decimal_point: List[Optional[str]]) -> None:
if len(decimal_point) != len(self):
raise IndexError()
for i in range(len(decimal_point)):
value = ord(decimal_point[i]) if decimal_point[i] is not None \
else 0
pango.pango_tab_array_set_decimal_point(self._pointer, i, value)

decimal_point: str = property(_get_decimal_point, _set_decimal_point)
"""
Unicode character to use as decimal point.
This is only relevant for tabs with :attr:`TabAlign.DECIMAL`
alignment, which align content at the first occurrence of the decimal
point character.
The default value of :const:`None` means that Pango will use the
decimal point according to the current locale.
:raises: :class:`IndexError` when trying to assign more or less
elements than defined tab stops.
"""

def _set_positions_in_pixels(self, positions_in_pixels: bool) -> None:
pango.pango_tab_array_set_positions_in_pixels(self._pointer,
positions_in_pixels)

def _get_positions_in_pixels(self) -> bool:
return pango.pango_tab_array_get_positions_in_pixels(self._pointer) \
!= 0

positions_in_pixels = property(_get_positions_in_pixels,
_set_positions_in_pixels)
"""
True if tab positions are in pixels.
"""
36 changes: 36 additions & 0 deletions tests/functional/test_tabarray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from pangocffi import (
TabArray, TabAlign
)
import unittest


class TestTabArray(unittest.TestCase):
def test_identity(self):
tabarray = TabArray()
assert len(tabarray) == 0
tabs = [(TabAlign.LEFT, 1), (TabAlign.LEFT, 10)]
tabarray.tabs = tabs
assert len(tabarray) == len(tabs)
assert tabarray.tabs == tabs

decimal_point = [':', ',']
tabarray.decimal_point = decimal_point
assert tabarray.decimal_point == decimal_point

assert tabarray.positions_in_pixels is False
tabarray.positions_in_pixels = True
assert tabarray.positions_in_pixels is True

def test_zero_size(self):
tabarray = TabArray()
assert len(tabarray) == 0
assert tabarray.tabs == []

def test_decimal_point_none(self):
tabarray = TabArray()

tabs = [(TabAlign.LEFT, 1), (TabAlign.LEFT, 10)]
tabarray.tabs = tabs
decimal_point = [None, None]
tabarray.decimal_point = decimal_point
assert tabarray.decimal_point == decimal_point

0 comments on commit 1d12c01

Please sign in to comment.